# Adapty Documentation (Full Content) > Complete documentation content across all platforms. Locale: tr Generated on: 2026-07-24T13:02:34.609Z --- # ANDROID - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.208Z Total files: 41 --- # File: sdk-installation-android --- --- title: "Android SDK'yı yükle ve yapılandır" description: "Abonelik tabanlı uygulamalar için Android'e Adapty SDK kurulumuna ilişkin adım adım kılavuz." --- Adapty SDK, mobil uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: Bu modül, platformlar arası paywalllar kolayca oluşturmaya yarayan kullanıcı dostu, kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. AdaptyUI, core modülüyle birlikte otomatik olarak etkinleştirilir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywallların gösterilmesi, satın almaların yapılması ve diğer temel işlevler dahil olmak üzere tam kurulumu sergileyen [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) göz atın. ::: ## Gereksinimler \{#requirements\} Minimum SDK gereksinimi: `minSdkVersion 21` :::info Adapty, Google Play Billing Library 8.x sürümüne kadar uyumludur. Varsayılan olarak Adapty, Google Play Billing Library v.7.0.0 ile çalışır; ancak daha yeni bir sürümü zorlamak isterseniz [bağımlılığı manuel olarak ekleyebilirsiniz](https://developer.android.com/google/play/billing/integrate#dependency). ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} Bağımlılık kurulum yönteminizi seçin: - Standart Gradle: Bağımlılıkları **modül düzeyindeki** `build.gradle` dosyanıza ekleyin - Projeniz `.gradle.kts` dosyaları kullanıyorsa, bağımlılıkları modül düzeyindeki `build.gradle.kts` dosyanıza ekleyin - Versiyon katalogları kullanıyorsanız, bağımlılıkları `libs.versions.toml` dosyanıza ekleyin ve ardından `build.gradle.kts` içinde referans verin [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Android.svg?style=flat&logo=android)](https://github.com/adaptyteam/AdaptySDK-Android/releases) ```groovy showLineNumbers dependencies { ... implementation platform('io.adapty:adapty-bom:') implementation 'io.adapty:android-sdk' // Only add this line if you plan to use Paywall Builder implementation 'io.adapty:android-ui' } ``` ```kotlin showLineNumbers dependencies { ... implementation(platform("io.adapty:adapty-bom:")) implementation("io.adapty:android-sdk") // Only add this line if you plan to use Paywall Builder: implementation("io.adapty:android-ui") } ``` ```toml showLineNumbers //libs.versions.toml [versions] .. adaptyBom = "" [libraries] .. adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } adapty = { module = "io.adapty:android-sdk" } // Only add this line if you plan to use Paywall Builder: adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... implementation(platform(libs.adapty.bom)) implementation(libs.adapty) // Only add this line if you plan to use Paywall Builder: implementation(libs.adapty.ui) } ``` Bağımlılık çözümlenemiyorsa, Gradle betiklerinizde `mavenCentral()` bulunduğundan emin olun.
Nasıl ekleneceğine dair talimat Projenizde `settings.gradle` dosyasında `dependencyResolutionManagement` yoksa, üst düzey `build.gradle` dosyanızın repositories bölümünün sonuna şunu ekleyin: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` Aksi takdirde, `settings.gradle` dosyanızdaki `dependencyResolutionManagement` bölümünün `repositories` kısmına şunu ekleyin: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... mavenCentral() } } ```
:::important Adapty Android SDK 4.0 ön sürümdür. Gradle, dinamik sürüm aralıkları (`+` veya `latest.release` gibi) üzerinden ön sürüm sürümlerini seçmez; bu nedenle tam sürümü sabitlemeniz gerekir. `adapty-bom` sürümünü 4.0 ön sürümüne ayarlayın — örneğin `io.adapty:adapty-bom:4.0.0-beta.2` ya da `libs.versions.toml` dosyasında `adaptyBom = "4.0.0-beta.2"`. BOM, eşleşen `android-sdk` ve `android-ui` sürümlerini sizin için çözer. Bkz. [Adapty Android SDK'yı v4'e Taşıma](migration-to-android-sdk-v4). ::: ## Adapty SDK'nın Adapty modülünü etkinleştir \{#activate-adapty-module-of-adapty-sdk\} ### Temel kurulum \{#basic-setup\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK'nın uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. ```kotlin showLineNumbers // In your Application class class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ) } } ``` ```java showLineNumbers // In your Application class public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( getApplicationContext(), new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ); } } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `Adapty.activate` tamamlanmasını bekleyin. Tam sıra için [Android SDK'da çağrı sırası](android-sdk-call-order) bölümüne bakın. ::: Şimdi uygulamanızda paywall'ları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız [Paywall Builder hızlı başlangıç kılavuzunu](android-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız [özel paywall'lar için hızlı başlangıç kılavuzuna](android-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştir \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız AdaptyUI modülüne ihtiyacınız var. Core modülü etkinleştirdiğinizde otomatik olarak etkinleştirilir; başka bir şey yapmanıza gerek yoktur. ## Proguard'ı yapılandır \{#configure-proguard\} Uygulamanızı production ortamına almadan önce Proguard yapılandırmanıza `-keep class com.adapty.** { *; }` satırını ekleyin. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kayıt sistemini ayarlayın \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki seviyeleri kullanabilirsiniz: | Seviye | Açıklama | | :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | | `AdaptyLogLevel.NONE` | Hiçbir şey loglanmaz. Varsayılan değer | | `AdaptyLogLevel.ERROR` | Yalnızca hatalar loglanır | | `AdaptyLogLevel.WARN` | Hatalar ve SDK'dan gelen kritik hata oluşturmayan ancak dikkat edilmesi gereken mesajlar loglanır. | | `AdaptyLogLevel.INFO` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır. | | `AdaptyLogLevel.VERBOSE` | Hata ayıklama sırasında işe yarayabilecek ek bilgiler (fonksiyon çağrıları, API sorguları vb.) loglanır. | Adapty'yi yapılandırmadan önce uygulamanızda log seviyesini ayarlayabilirsiniz. ```kotlin showLineNumbers Adapty.logLevel = AdaptyLogLevel.VERBOSE //recommended for development and the first production release ``` ```java showLineNumbers Adapty.setLogLevel(AdaptyLogLevel.VERBOSE); //recommended for development and the first production release ``` #### Günlük sistemi mesajlarını yönlendirme \{#redirect-the-logging-system-messages\} Herhangi bir nedenle Adapty'den gelen mesajları kendi sisteminize göndermek veya bir dosyaya kaydetmek istiyorsanız, varsayılan davranışı geçersiz kılabilirsiniz: ```kotlin showLineNumbers Adapty.setLogHandler { level, message -> //handle the log } ``` ```java showLineNumbers Adapty.setLogHandler((level, message) -> { //handle the log }); ``` ### Veri politikaları \{#data-policies\} Adapty, açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz; ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşmayı devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. IP tabanlı özelliklere ihtiyaç duyulmadığında kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da gereksiz veri toplamayı azaltmak için bu parametreyi kullanın. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build(); ``` #### Reklam kimliği (Ad ID) toplama ve paylaşmayı devre dışı bırakma \{#disable-advertising-id-ad-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcının [reklam kimliği](https://support.google.com/googleplay/android-developer/answer/6048248) toplanmasını devre dışı bırakmak için `adIdCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi Play Store politikalarına uymak, reklam kimliği izin istemini tetiklemekten kaçınmak ya da uygulamanız reklam kimliğine dayalı attribution veya analiz gerektirmiyorsa kullanın. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build(); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, performansı artırmak ve ağ kullanımını azaltmak için varsayılan olarak medyayı (görsel ve video gibi) önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. `AdaptyUI.configureMediaCache` yöntemini kullanarak varsayılan önbellek boyutunu ve geçerlilik süresini değiştirebilirsiniz. Bu adım isteğe bağlıdır; bu yöntemi çağırmazsanız varsayılan değerler kullanılır (100 MB disk boyutu, 7 gün geçerlilik süresi). ```kotlin showLineNumbers val cacheConfig = MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(3.days) .build() AdaptyUI.configureMediaCache(cacheConfig) ``` ```java showLineNumbers MediaCacheConfiguration cacheConfig = new MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(TimeInterval.days(3)) .build(); AdaptyUI.configureMediaCache(cacheConfig); ``` **Parametreler:** | Parametre | Zorunluluk | Açıklama | |-------------------------|----------|-----------------------------------------------------------------------------| | diskStorageSizeLimit | isteğe bağlı | Diskteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer 100 MB'tır. | | diskCacheValidityTime | isteğe bağlı | Önbelleğe alınan dosyaların geçerli sayıldığı süre. Varsayılan değer 7 gündür. | :::tip `AdaptyUI.clearMediaCache(strategy)` kullanarak medya önbelleğini çalışma zamanında temizleyebilirsiniz. `strategy` parametresi `CLEAR_ALL` veya `CLEAR_EXPIRED_ONLY` olabilir. ::: ### Gizlenmiş hesap kimliklerini ayarlama \{#set-obfuscated-account-ids\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryolarında gizlenmiş hesap kimliklerini zorunlu kılar. Bu kimlikler, Google Play'in kullanıcı bilgilerini anonim tutarken satın alımları tanımlamasına yardımcı olur; bu durum özellikle sahtekarlığı önleme ve analitik açısından önem taşır. Uygulamanız hassas kullanıcı verileri işliyorsa ya da belirli gizlilik düzenlemelerine uymak zorundaysanız bu kimlikleri ayarlamanız gerekebilir. Gizlenmiş kimlikler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın alımları takip etmesini sağlar. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build(); ``` ### Adapty'yi özel bir process'te çalıştırma \{#run-adapty-in-a-custom-process\} Varsayılan olarak Adapty yalnızca uygulamanızın ana process'inde çalışabilir. Uygulamanız birden fazla process kullanıyorsa, Adapty'yi yalnızca bir kez başlatın; aksi takdirde beklenmedik davranışlar oluşabilir. Adapty'yi farklı bir process'te çalıştırmanız gerekiyorsa, bunu yapılandırmanızda belirtin: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build(); ``` Bu değeri ayarlamadan Adapty'yi başka bir process'te etkinleştirmeye çalışırsanız, SDK bir uyarı kaydeder ve etkinleştirmeyi atlar. ### Yerel access level'ları etkinleştirme \{#enable-local-access-levels\} Varsayılan olarak, Android'de [yerel access level'lar](local-access-levels) devre dışıdır. Etkinleştirmek için `withLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build(); ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Auto Backup yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmalarıyla birlikte gelir. Yedekleme kuralları tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirici `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ifadelerinden bahseden bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/sample_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` Bunu çözmek için şunları yapmanız gerekir: - Manifest birleştiriciye, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty ve diğer SDK'lardan gelen yedekleme kurallarını tek bir XML dosyasında (ya da Android 12+ için bir çift dosyada) birleştirin. #### 1. Manifest'inize `tools` namespace'ini ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} Henüz eklenmemişse, kök `` etiketine `tools` namespace'ini ekleyin: ```xml ... ``` #### 2. `` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Uygulamanızın `AndroidManifest.xml` dosyasında `` etiketini güncelleyin; böylece uygulamanız son değerleri sağlar ve manifest birleştirici, kütüphane değerlerini değiştirsin: ```xml ... ``` Herhangi bir SDK da `android:allowBackup` ayarlıyorsa, bunu `tools:replace` listesine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralları dosyaları oluşturun \{#3-create-merged-backup-rules-files\} `app/src/main/res/xml/` dizini altında, Adapty'nin kurallarını diğer SDK'lardan gelen kurallarla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümlerinde uyumluluğu sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri ayıklama kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" ``` **Android 11 ve altı için** (eski tam yedekleme içerik formatını kullanır): ```xml title="sample_backup_rules.xml" ``` Bu kurulumla: - Adapty'nin yedekleme dışı tutmaları (`AdaptySDKPrefs.xml`) korunur. - Diğer SDK'ların dışı tutmaları (örneğin, `appsflyer-data`) da uygulanır. - Manifest birleştirici, uygulamanızın yapılandırmasını kullanır ve çakışan yedekleme özelliklerinde artık hata vermez. #### Başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app\} Satın alma akışını başlatan Activity, varsayılan olmayan bir `launchMode` kullanıyorsa, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan geri döndüğünde Android bu Activity'yi hatalı biçimde yeniden oluşturabilir ya da yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına veya iptal edilmiş olarak işlenmesine yol açabilir. Satın almaların doğru çalışmasını sağlamak için, satın alma akışını başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın; diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma akışını başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml ``` --- # File: android-quickstart-paywalls --- --- title: "Android SDK'da Flow Builder ile satın alımları etkinleştirme" description: "Adapty Flow Builder ile uygulama içi satın alımları etkinleştirmek için hızlı başlangıç kılavuzu." --- Uygulama içi satın alımları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – ürünleri kullanıcılara sunan ekran dizileri; no-code Flow Builder ile oluşturulur. SDK bunları `getFlow` aracılığıyla alır. Arayüzü kendi kodunuzla oluşturmayı tercih ediyorsanız bunun yerine paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](android-quickstart-manual). - [**Placement'lar**](placements) – flow'ların uygulamanızda nerede ve ne zaman gösterileceği (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın almaları etkinleştirmek için size üç yöntem sunar. Uygulama gereksinimlerinize bağlı olarak birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [satın almaya hazır eksiksiz bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder; tüm karmaşık satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda kendisi halleder. | | Manuel oluşturulan paywall'lar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine de Adapty'den alırsınız. [Kılavuza](android-quickstart-manual) bakın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı sınırlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl hayata geçirileceğini göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, [Paywall'ları manuel olarak uygulama](android-quickstart-manual) bölümüne bakın. ::: Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Görüntüleyin, satın alma işlemlerini Adapty yönetsin**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butona tıkladığında bağlantıları açın veya flow'u kapatın. ## Başlamadan Önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Adapty Kontrol Paneli'nde [uygulamanızı Google Play'e bağlayın](initial-android). 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ürünleri ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'unuzu ekleyin](create-placement). 5. Uygulama kodunuza [Adapty SDK'yı yükleyin ve etkinleştirin](sdk-installation-android). Bu kılavuz Adapty Android SDK v4 API'lerini kullanmaktadır. :::tip Bu adımları tamamlamanın en hızlı yolu [hızlı başlangıç kılavuzunu](quickstart) takip etmek ya da [Developer CLI](developer-cli-quickstart) kullanarak flow'lar ve placement'lar oluşturmaktır. ::: ## 1. Flow'u alın \{#get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturduğunuz bir flow'u almak için şunları yapmanız gerekir: 1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın ve bir görünüm yapılandırmasına sahip olup olmadığını kontrol edin. 2. `getFlowConfiguration` metodunu kullanarak görünüm yapılandırmasını alın. Görünüm yapılandırması, flow'u görüntülemek için gereken UI öğelerini ve stil bilgilerini içerir. :::important Görünüm yapılandırmasını almak için Flow Builder'da **Show on device** geçişini açmanız gerekir. Aksi takdirde boş bir görünüm yapılandırması alırsınız ve flow görüntülenmez. ::: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> if (result is AdaptyResult.Success) { val flow = result.value if (!flow.hasViewConfiguration) { return@getFlow } AdaptyUI.getFlowConfiguration(flow) { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value } } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); if (!flow.hasViewConfiguration()) { return; } AdaptyUI.getFlowConfiguration(flow, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) configResult).getValue(); // use loaded configuration } }); } }); ``` ## 2. Flow'u göster \{#display-the-flow\} Artık flow yapılandırmanız hazır olduğunda, flow'unuzu görüntülemek için birkaç satır kod eklemeniz yeterlidir. Görsel flow'u cihaz ekranında gösterebilmek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın ya da doğrudan `AdaptyFlowView` oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, null, // products = null means auto-fetch eventListener, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, null, // products = null means auto-fetch eventListener, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, null, // products = null means auto-fetch eventListener ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //add to the view hierarchy if needed, or you receive it from xml ... flowView.showFlow(flowConfiguration, products, eventListener); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, view hiyerarşisine ekleyebilir ve cihaz ekranında görüntüleyebilirsiniz. :::tip Bir flow'un nasıl görüntüleneceğine ilişkin daha fazla ayrıntı için [kılavuzumuza](android-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetme \{#handle-button-actions\} Kullanıcılar flow içindeki butonlara tıkladığında, Android SDK satın alma, geri yükleme, flow'u kapatma ve bağlantı açma işlemlerini otomatik olarak gerçekleştirir. Ancak bazı butonların özel veya önceden tanımlanmış ID'leri vardır ve bu eylemler kodunuzda ele alınmalıdır. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, aşağıda kapat butonunun varsayılan davranışı gösterilmektedir. Bunu koda eklemeniz gerekmez, ancak gerekirse nasıl yapıldığını buradan görebilirsiniz. :::tip Buton [action'ları](android-handle-paywall-actions) ve [event'leri](android-handling-events) nasıl yöneteceğinizi anlatan kılavuzlarımızı okuyun. ::: ```kotlin showLineNumbers title="Kotlin" override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ```java showLineNumbers @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada görüntülenmeye hazır. Paywall üzerinden test satın alımı tamamlayabildiğinizden emin olmak için [Google Play Store'da satın alımlarınızı test edin](testing-on-android). Şimdi, doğru kullanıcılara paywall gösterdiğinizden veya ücretli özelliklere erişim sağladığınızdan emin olmak için [kullanıcıların access level'ını kontrol etmeniz](android-check-subscription-status) gerekir. ## Tam örnek \{#full-example\} Tüm bu adımları uygulamanızda nasıl bir araya getirebileceğiniz aşağıda gösterilmektedir. ```kotlin showLineNumbers title="Kotlin" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Adapty.getFlow("YOUR_PLACEMENT_ID") { flowResult -> if (flowResult is AdaptyResult.Success) { val flow = flowResult.value if (!flow.hasViewConfiguration) { // Use custom logic return@getFlow } AdaptyUI.getFlowConfiguration(flow) { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value val flowView = AdaptyUI.getFlowView( this, flowConfiguration, null, // products = null means auto-fetch object : AdaptyFlowDefaultEventListener() { override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Close -> { (context as? Activity)?.onBackPressed() } } } } ) setContentView(flowView) } } } } } } ``` ```java showLineNumbers public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Adapty.getFlow("YOUR_PLACEMENT_ID", flowResult -> { if (flowResult instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) flowResult).getValue(); if (!flow.hasViewConfiguration()) { // Use custom logic return; } AdaptyUI.getFlowConfiguration(flow, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) configResult).getValue(); AdaptyFlowView flowView = AdaptyUI.getFlowView( this, flowConfiguration, null, // products = null means auto-fetch new AdaptyFlowDefaultEventListener() { @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } } ); setContentView(flowView); } }); } }); } } ``` --- # File: android-check-subscription-status --- --- title: "Android SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Android uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriklere erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) bilgisini kontrol etmeniz gerekir. Bu makale, kullanıcılara paywall göstermeniz mi yoksa ücretli özelliklere erişim izni vermeniz mi gerektiğine karar vermek için profil durumuna nasıl erişeceğinizi gösterir. ## Abonelik durumunu al \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profilindeki [access level](access-level) bilgisini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verilerine ihtiyaç duyduğunuzda (ör. uygulama açılışında) veya zorla güncelleme yapmak istediğinizde `getProfile` çağrısı yapın. - Abonelik durumu değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** ayarlayın. ### Profili al \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### Abonelik güncellemelerini dinle \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek üzere `Adapty.setOnProfileUpdatedListener()` kullanın. Kullanıcının abonelik durumu değiştiğinde Adapty bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncel profil verisini saklayın; böylece uygulamanız genelinde ek ağ isteği yapmadan kullanabilirsiniz. ```kotlin class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true } } ``` ```java public class SubscriptionManager { private AdaptyProfile currentProfile; public SubscriptionManager() { // Listen for profile updates Adapty.setOnProfileUpdatedListener(profile -> { this.currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() public boolean hasAccess() { if (currentProfile == null) { return false; } AdaptyAccessLevel premiumAccess = currentProfile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); return premiumAccess != null && premiumAccess.isActive(); } } ``` :::note Adapty, uygulamanız başladığında profil güncelleme dinleyicisini otomatik olarak çağırır; cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sunar. ::: ## Profili paywall mantığıyla ilişkilendir \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim izni verme konusunda anında karar vermeniz gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım, uygulama açılışı, premium bölümlere girilmesi veya belirli içerikler gösterilmeden önce gibi senaryolarda kullanışlıdır. ```kotlin private fun initializePaywall() { loadPaywall { paywallView -> checkAccessLevel { result -> when (result) { is AdaptyResult.Success -> { if (!result.value && paywallView != null) { setContentView(paywallView) // Show paywall if no access } } is AdaptyResult.Error -> { if (paywallView != null) { setContentView(paywallView) // Show paywall if access check fails } } } } } } private fun checkAccessLevel(callback: ResultCallback) { Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val hasAccess = result.value.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true callback.onResult(AdaptyResult.Success(hasAccess)) } is AdaptyResult.Error -> { callback.onResult(AdaptyResult.Error(result.error)) } } } } ``` ```java private void initializePaywall() { loadPaywall(paywallView -> { checkAccessLevel(result -> { if (result instanceof AdaptyResult.Success) { boolean hasAccess = ((AdaptyResult.Success) result).getValue(); if (!hasAccess && paywallView != null) { setContentView(paywallView); // Show paywall if no access } } else if (result instanceof AdaptyResult.Error) { if (paywallView != null) { setContentView(paywallView); // Show paywall if access check fails } } }); }); } private void checkAccessLevel(ResultCallback callback) { Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyAccessLevel premiumAccess = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); boolean hasAccess = premiumAccess != null && premiumAccess.isActive(); callback.onResult(AdaptyResult.success(hasAccess)); } else if (result instanceof AdaptyResult.Error) { callback.onResult(AdaptyResult.error(((AdaptyResult.Error) result).getError())); } }); } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların ödedikleri içeriklere erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](android-quickstart-identify) öğrenin. --- # File: android-quickstart-identify --- --- title: "Android SDK'da kullanıcıları tanımlama" description: "Android'de uygulama içi abonelik yönetimi için Adapty'yi kurmanın hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa sizin için hazırlanmıştır. Burada, Adapty'deki kullanıcı profilleriyle mevcut kimlik doğrulama sisteminizi nasıl uyumlu hale getireceğinizi öğreneceksiniz. ::: Kullanıcı satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline göre değişir: - Uygulamanız backend kimlik doğrulaması kullanmıyorsa ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılarla ilgili bölüme](#anonymous-users) bakın. - Uygulamanızda backend kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılarla ilgili bölüme](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmadan)** veya tanımlanmış **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi iç kimlik doğrulama sisteminizle eşleştirmek için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar şunlardır: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |-------------------------|-------------------------------------------------------|---------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar genelinde aynı profil | | **Veri sürekliliği** | Anonim kullanıcı verileri uygulama kurulumuna bağlıdır | Tanımlanmış kullanıcı verileri uygulama kurulumları arasında devam eder | ## Anonim kullanıcılar \{#anonymous-users\} Backend kimlik doğrulamanız yoksa **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profiliyle ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **etkinleştirme sırasında yeni bir anonim profil oluşturur**. 4. Kullanıcı uygulamanızda daha önce satın alma yapmışsa, varsayılan olarak satın almaları SDK etkinleştirmesinde App Store'dan otomatik olarak senkronize edilir. Yani anonim kullanıcılarda her kurulumda yeni profil oluşturulur; ancak bu bir sorun değildir çünkü Adapty analizinde [yeni kurulum olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için kurulumları **cihaz kimliklerine** göre saymanız gerekir. Bu durumda, yeniden kurulumlar dahil olmak üzere bir cihazdaki her uygulama kurulumu bir kurulum olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamada kullanıcıları tanımlamak için iki seçeneğiniz vardır: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğruladıklarında `identify()` metodunu customer user ID ile çağırın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başladığında zaten bir customer user ID'niz varsa, `activate()` çağrısında gönderin. :::important Varsayılan olarak, Adapty halihazırda başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; böylece her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Daha fazla ayrıntı için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başladıktan sonra tanımlıyorsanız (örneğin uygulamanıza giriş yaptıktan veya kayıt olduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty bunu otomatik olarak mevcut profile bağlar. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır. Parametre değerini sabit kodlarsanız, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir. ::: Diğer SDK metodlarını çağırmadan önce `identify` tamamlanma callback'inin tetiklenmesini bekleyin. Eş zamanlı çağrılar, tanımlanmış profil yerine anonim profile düşebilir. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Her kullanıcı için benzersiz if (error == null) { // başarılı identify } } ``` ```java showLineNumbers // Kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // başarılı identify } }); ``` ### SDK etkinleştirmesi sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` metodunu ayrıca çağırmak yerine `activate` metodunda gönderebilirsiniz. Customer user ID'yi bilmenize rağmen yalnızca etkinleştirmeden sonra ayarlarsanız, etkinleştirme sırasında Adapty yeni bir anonim profil oluşturacak ve `identify` metodunu çağırdıktan sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane iletebilirsiniz. Yeni bir tane iletirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID'ye bağlanır. :::note Varsayılan olarak, anonim profil oluşturma analiz panolarını etkilemez çünkü kurulumlar cihaz kimliklerine göre sayılır. Bir cihaz kimliği, cihazdaki mağazadan yapılan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, bunun ilk mi yoksa tekrarlanan bir kurulum mu olduğuna veya mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturmak (SDK etkinleştirmesinde veya çıkış yapıldığında), oturum açmak veya uygulamayı yeniden yüklemeden yükseltmek ek kurulum olayları oluşturmaz. Kurulumları cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) seçeneğini yapılandırın. ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build(); ``` ### Kullanıcı oturumunu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir düğmeniz varsa, `logout` metodunu kullanın. :::important Kullanıcı oturumunun kapatılması, kullanıcı için yeni bir anonim profil oluşturur. ::: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` :::info Kullanıcıları tekrar uygulamaya giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın alma izni verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıktan sonra erişimlerini koruduklarından emin olmanız gerekir: 1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil kimliğine bağlar. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin satın alma kayıt öncesinde yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), profil geçişinden sonra gerçek access level'ı almanız gerekir. Tanımlamadan hemen sonra [`getProfile`](android-check-subscription-status) metodunu çağırabilir veya verilerin otomatik olarak senkronize olması için [profil güncellemelerini dinleyebilirsiniz](android-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını hayata geçirdiniz! Uygulamanızın monetizasyonunda başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboarding'ler**](android-onboardings): Onboarding'lerle kullanıcıları etkileyin ve elde tutmayı artırın - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analiz hizmetleriyle entegre olun - [**Özel profil özellikleri belirleme**](android-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segment'ler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-android --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Android uygulamanıza entegre edin" description: "Android uygulamanıza Adapty SDK'sını uçtan uca entegre etmek için adapty-sdk-integration becerisini AI kodlama aracınızla kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu özellik beta aşamasındadır. Takılırsa veya beklenmedik şekilde davranırsa, bunun yerine [adım adım entegrasyon kılavuzunu](adapty-cursor-android) izleyin — yapay zeka aracınıza her aşamada doğru dokümanlarla rehberlik eder. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-android --- --- title: "Adapty'yi Android uygulamanıza AI yardımıyla entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi Android uygulamanıza adım adım entegre etme kılavuzu." --- Bu kılavuz, bir yapay zeka kodlama aracıyla Adapty'yi Android uygulamanıza adım adım entegre etmenizi sağlar; doğru Adapty dokümanlarını doğru sırayla besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı yapılandırmalar gerektirir. Bunu etkileşimli bir LLM becerisini kullanarak ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywall'larınızı ve placement'larınızı doğrudan Kontrol Panelini açmadan ayarlamasını sağlar. Yalnızca [mağazanızı bağlamanız](integrate-payments) Kontrol Paneli üzerinden yapılması gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra, agent'ınızda `/adapty-cli` komutunu çalıştırın. Her adımda — mağazanızı bağlamak için Kontrol Panelini açmanız gereken anlar dahil — sizi yönlendirecektir. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin yerinize bulamaz — bunları kendiniz sağlamanız gerekir. 1. **App store bağlantısı kurun**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Satın almaların çalışması için bu zorunludur. [Google Play'i bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin ve **API keys** bölümünü bulun. Kodda bu, Adapty yapılandırma builder'ına geçirdiğiniz string'dir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere kodda doğrudan başvurmazsınız — Adapty bunları paywall'lar aracılığıyla iletir. [Ürün ekleyin](quickstart-products) 4. **Bir paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasından bir paywall oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `Adapty.getPaywall("YOUR_PLACEMENT_ID")` çağrısına geçirdiğiniz string'dir. [Paywall oluşturun](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde her ürün için **Products** sayfasından yapılandırın. Kodda bu, `profile.accessLevels["premium"]?.isActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için uygundur. Ödeme yapan kullanıcılar ürüne bağlı olarak farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), koda başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Bu beşine sahip olduğunuzda, kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodu üretebilir. ::: ### Hazır olduğunuzda kurun \{#set-up-when-ready\} Bunlar kod yazmaya başlamak için zorunlu değil, ancak entegrasyon olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## Adapty dokümanlarını LLM'inize gönderin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi kullanın (önerilen) \{#use-context7-recommended\} [Context7](https://context7.com), LLM'inize güncel Adapty dokümantasyonuna doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, sorduklarınıza göre doğru dokümanları otomatik olarak çeker — manuel URL yapıştırmanıza gerek yoktur. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurmak için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, prompt'larınızda Adapty kütüphanesine başvurun: ``` Use the adaptyteam/adapty-docs library to look up how to install the Android SDK ``` :::warning Context7, doküman bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalıştığından emin olmak için aşağıdaki [uygulama adım adım rehberini](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Herhangi bir Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** butonuna tıklayın. Örneğin: [adapty-cursor-android.md](https://adapty.io/docs/tr/adapty-cursor-android.md). Aşağıdaki [uygulama adım adım rehberindeki](#implementation-walkthrough) her aşama, yapıştırmanız için `.md` bağlantıları içeren bir "LLM'inize gönderin" bloğu içerir. Aynı anda daha fazla dokümantasyon için aşağıdaki [index dosyaları ve platforma özgü alt kümeler](#plain-text-doc-index-files) bölümüne bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, uygulama sırasına göre Adapty entegrasyonunu ele alır. Her aşamada LLM'inize gönderilecek dokümanlar, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar yer alır. ### Entegrasyonunuzu planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), herhangi bir kod yazmadan önce LLM'in hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize hangi satın alma yaklaşımını kullandığınızı söyleyin — bu, takip etmesi gereken rehberleri etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin kodsuz builder'ında paywall'lar oluşturursunuz ve SDK bunları otomatik olarak gösterir. - [**Manuel olarak oluşturulan paywall'lar**](android-making-purchases): Kendi paywall arayüzünüzü kodla oluşturursunuz, ancak ürünleri çekmek ve satın almaları yönetmek için yine de Adapty kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](android-quickstart-paywalls) okuyun. ### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\} Android Studio'da Gradle aracılığıyla Adapty SDK bağımlılığını ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temeldir — bu olmadan hiçbir şey çalışmaz. **Rehber:** [Adapty SDK'yı yükleyin ve yapılandırın](sdk-installation-android) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-android.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Uygulama derlenir ve çalışır. Logcat'te Adapty etkinleştirme logu görünür. - **Dikkat:** "Public API key is missing" → App settings'den gerçek anahtarınızla yer tutucuyu değiştirdiğinizi kontrol edin. ::: ### Paywall'ları gösterin ve satın almaları yönetin \{#show-paywalls-and-handle-purchases\} Placement ID'ye göre bir paywall çekin, gösterin ve satın alma olaylarını yönetin. İhtiyacınız olan rehberler, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerlerken sandbox'ta test edin — sonuna kadar beklemeyin. Kurulum talimatları için [Sandbox'ta satın almaları test etme](test-purchases-in-sandbox) sayfasına bakın. **Rehberler:** - [Paywall'ları kullanarak satın almaları etkinleştirin (hızlı başlangıç)](android-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını çekin](android-get-pb-paywalls) - [Paywall'ları gösterin](android-present-paywalls) - [Paywall olaylarını yönetin](android-handling-events) - [Buton eylemlerine yanıt verin](android-handle-paywall-actions) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-paywalls.md - https://adapty.io/docs/tr/android-get-pb-paywalls.md - https://adapty.io/docs/tr/android-present-paywalls.md - https://adapty.io/docs/tr/android-handling-events.md - https://adapty.io/docs/tr/android-handle-paywall-actions.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma diyalogunu açar. - **Dikkat:** Boş paywall veya `getPaywall` hatası → placement ID'nin kontrol paneliyle tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: **Rehberler:** - [Özel paywall'ınızda satın almaları etkinleştirin (hızlı başlangıç)](android-quickstart-manual) - [Paywall'ları ve ürünleri çekin](fetch-paywalls-and-products-android) - [Remote config ile tasarlanmış paywall'ı gösterin](present-remote-config-paywalls-android) - [Satın alma yapın](android-making-purchases) - [Satın almaları geri yükleyin](android-restore-purchase) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-android.md - https://adapty.io/docs/tr/present-remote-config-paywalls-android.md - https://adapty.io/docs/tr/android-making-purchases.md - https://adapty.io/docs/tr/android-restore-purchase.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Özel paywall'ınız, Adapty'den çekilen ürünleri gösterir. Bir ürüne dokunmak sandbox satın alma diyalogunu açar. - **Dikkat:** Boş ürün dizisi → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitlesi olduğunu doğrulayın. ::: **Rehberler:** - [Observer mode genel bakış](observer-vs-full-mode) - [Observer mode'u uygulayın](implement-observer-mode-android) - [Observer mode'da işlemleri bildirin](report-transactions-observer-mode-android) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-android.md - https://adapty.io/docs/tr/report-transactions-observer-mode-android.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızla sandbox satın alması yapıldıktan sonra işlem, Adapty kontrol panelindeki **Event Feed**'de görünür. - **Dikkat:** Olay yok → Adapty'ye işlem bildirdiğinizi ve Google Play Real-Time Developer Notifications'ın yapılandırıldığını doğrulayın. ::: ### Abonelik durumunu kontrol edin \{#check-subscription-status\} Satın alma sonrasında, premium içeriği kilitlemek için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin. **Rehber:** [Abonelik durumunu kontrol edin](android-check-subscription-status) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın alması sonrasında `profile.accessLevels["premium"]?.isActive` değeri `true` döner. - **Dikkat:** Satın alma sonrası `accessLevels` boş → ürünün kontrol panelinde bir access level'a atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Satın almaların cihazlar arasında kalıcı olması için uygulama kullanıcı hesaplarınızı Adapty profilleriyle ilişkilendirin. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Rehber:** [Kullanıcıları tanımlayın](android-quickstart-identify) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/android-quickstart-identify.md ``` :::tip[Kontrol Noktası] - **Beklenen:** `Adapty.identify("your-user-id")` çağrısından sonra, kontrol panelinin **Profiles** bölümünde özel kullanıcı ID'niz görünür. - **Dikkat:** Anonim profil atıfını önlemek için `identify`'ı, aktivasyondan sonra ancak paywall'ları çekmeden önce çağırın. ::: ### Yayın için hazırlanın \{#prepare-for-release\} Entegrasyonunuz sandbox'ta çalışır hale geldikten sonra, her şeyin canlı ortama hazır olduğundan emin olmak için yayın kontrol listesini inceleyin. **Rehber:** [Yayın kontrol listesi](release-checklist) LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Tüm kontrol listesi öğeleri onaylandı: mağaza bağlantısı, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Google Play Real-Time Developer Notifications eksik → **App settings → Android SDK** bölümünden yapılandırın, aksi takdirde olaylar kontrol panelinde görünmez. ::: ## Düz metin dokümantasyon index dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty dokümantasyonunu listeleyen veya birleştiren index dosyalarına sahibiz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı AI agent'ları için (ör. ChatGPT) `llms.txt` dosyasını indirip sohbete dosya olarak yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hali. Çok büyük — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Android'e özgü [`android-llms.txt`](https://adapty.io/docs/tr/android-llms.txt) ve [`android-llms-full.txt`](https://adapty.io/docs/tr/android-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: android-get-pb-paywalls --- --- title: "Flow ve paywall'ları getir - Android" description: "Android uygulamanızda Adapty'den flow ve paywall'ları çekin." --- [flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda görüntüleyebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'ı ve görünüm yapılandırmasını almaktır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. :::
Uygulamanızda flow'ları görüntülemeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-android) yükleyin.
## Flow/paywall getirme \{#fetch-flowpaywall\} Bir flow veya paywall'ı Flow Builder ya da Paywall Builder kullanarak tasarladıysanız, kullanıcıya göstermek için mobil uygulama kodunuzda bunu render etme konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. Bununla birlikte, placement üzerinden ID'sini, görünüm yapılandırmasını almanız ve ardından onu mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, flow veya paywall'ı ve [görünüm yapılandırmasını](android-get-pb-paywalls#fetch-the-view-configuration) mümkün olduğunca erken almanız kritik öneme sahiptir; bu sayede kullanıcıya gösterilmeden önce görsellerin indirilmesi için yeterli zaman tanınmış olur. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```kotlin showLineNumbers ... Adapty.getFlow("YOUR_PLACEMENT_ID", loadTimeout = 10.seconds) { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow/paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers ... Adapty.getFlow("YOUR_PLACEMENT_ID", TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow/paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmesi için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir; ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında ağ isteklerini önlemek amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK, flow'ları ve paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Ayrıca daha hızlı getirmek için CDN ve CDN'e ulaşılamadığı durumlarda bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en son sürümü aldığınızdan emin olmak için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, bu metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`; burada `.seconds`, `import com.adapty.utils.seconds`'tan gelir) ya da `TimeInterval.seconds(5)` şeklinde kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, remote config'ler ve flow'un bir görünüm yapılandırması içerip içermediğini belirten `hasViewConfiguration` bayrağını barındıran bir `AdaptyFlow` nesnesi. Ön yükleme, özel UI veya programatik kontroller için gerçek ürünleri çekmek üzere `getPaywallProducts(flow)` çağrısını kullanın. | ## View konfigürasyonunu alma \{#fetch-the-view-configuration\} Flow veya paywall'ı aldıktan sonra, `flow.hasViewConfiguration` ile bir view konfigürasyonu içerip içermediğini kontrol edin. Bu bayrak, placement'ın Adapty Kontrol Paneli'nde nasıl tasarlandığını ayırt eder: - **`true`** — placement, **Flow Builder** (bir flow) veya **Paywall Builder** (bir paywall) ile tasarlanmış. Adapty, arayüzü sizin için render eder. Görünüm yapılandırmasını almak ve [flow veya paywall'ı sunmak](android-present-paywalls) için aşağıdaki adımlara devam edin. - **`false`** — placement, Builder arayüzü olmayan özel bir paywall. [Remote config paywall olarak ele alın](present-remote-config-paywalls-android). :::important Flow Builder'da **Show on device** geçişinin etkinleştirildiğinden emin olun. Bu seçenek açık değilse görünüm yapılandırması alınamaz. ::: Görünüm yapılandırmasını yüklemek için `getFlowConfiguration` metodunu kullanın. ```kotlin showLineNumbers if (!flow.hasViewConfiguration) { // use your custom logic return } AdaptyUI.getFlowConfiguration(flow, loadTimeout = 10.seconds) { result -> when(result) { is AdaptyResult.Success -> { val flowConfiguration = result.value // use loaded configuration } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **locale** |

isteğe bağlı

varsayılan: cihaz dili

| [Yerelleştirmenin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı; `-` ile ayrılmış bir veya iki alt etiket içeren dil kodu olarak beklenir (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve dil kodları](android-localizations-and-locale-codes). | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metod, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir; zira işlem arka planda farklı isteklerden oluşuyor olabilir. |
Görünüm yapılandırmasını yüklemek için `getFlowConfiguration` metodunu kullanın. ```java showLineNumbers if (!flow.hasViewConfiguration()) { // use your custom logic return; } AdaptyUI.getFlowConfiguration(flow, TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyUI.FlowConfiguration flowConfiguration = ((AdaptyResult.Success) result).getValue(); // use loaded configuration } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **locale** |

isteğe bağlı

varsayılan: cihaz dili

| Bir veya iki alt etiket içeren dil kodu formatında beklenen [yerelleştirme](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı; etiketler `-` ile ayrılır (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes). | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbellekteki veriler veya yerel yedek döndürülür. Nadir durumlarda bu metot, arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir. |
:::note Birden fazla dil kullanıyorsanız, [Builder yerelleştirmesinin nasıl ekleneceğini](add-paywall-locale-in-adapty-paywall-builder) ve yerel ayar kodlarının nasıl doğru kullanılacağını [buradan](android-localizations-and-locale-codes) öğrenin. ::: Yüklendikten sonra [flow veya paywall'ı gösterin](android-present-paywalls). ## Varsayılan kitle için bir flow veya paywall alarak daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında yüklenir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall yüklemek istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak çok önemlidir: önerilen yaklaşım, flow veya paywall'ı yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklanan `getFlow` metoduyla getirmektir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı flow'lar göstermeniz gerekiyorsa bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız gerekecek ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecek. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Eğer daha hızlı flow veya paywall yükleme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // the requested flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneririz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu senaryoda kullanıcılar en son veriye ulaşamayabilir; ancak internet bağlantısı ne kadar dengesiz olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizleme yapıldığında temizlendiğini unutmayın.

| ## Varlıkları özelleştir \{#customize-assets\} Flow veya paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görselleri ve videolarının önceden tanımlanmış kimlikleri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri kimliklerine göre hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir kimlik belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Bir video başlamadan önce önizleme görseli gösterin. İşte özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, ) ``` :::note Bir asset bulunamazsa, flow varsayılan görünümüne geri döner. ::: Videolar için, isteğe bağlı olarak bir `resolution` geçerek video yüklenmeden önce düzen alanını ayırabilir ve en boy oranını (`width / height`) belirleyebilirsiniz: ```kotlin showLineNumbers AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), resolution = AdaptyCustomVideoAsset.Resolution(width = 1080, height = 1920), ) ```
[Adapty Kontrol Paneli](adapty-paywall-builder)'nda yeni Paywall Builder ile [paywall'ınızın görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywall'ı ve görünüm yapılandırmasını almaktır. :::warning Yeni Paywall Builder, Android SDK 3.0 veya daha yüksek sürümüyle çalışır. ::: Paywall Builder ile özelleştirilmiş paywalllar için bu konuya başvurduğunuzu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywallları için paywallları ve ürünleri getirme](fetch-paywalls-and-products-android) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. :::
Mobil uygulamanızda paywallları görüntülemeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'unuzu ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-android) yükleyin.
## Paywall Builder ile tasarlanan paywallı getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem paywall içinde neyin gösterileceğini hem de nasıl gösterileceğini içerir. Yine de placement aracılığıyla ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, kullanıcıya göstermeden önce görsellerin indirilmesine yeterli süre tanımak amacıyla paywallı ve [görünüm yapılandırmasını](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız önemlidir. Paywall almak için `getPaywall` metodunu kullanın: ```kotlin showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en", loadTimeout = 10.seconds) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi ise bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu yaklaşımı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.

Adapty SDK, paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN ve CDN'e ulaşılamadığı durumlarda bağımsız bir yedek sunucu da kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywalllarınızın her zaman en son sürümünü almanızı garantilemek için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı işlevleriyle oluşturabilirsiniz (örneğin `5.seconds`, burada `.seconds` `import com.adapty.utils.seconds`'dan gelir) veya `TimeInterval.seconds(5)` şeklinde kullanabilirsiniz. Sınırlama koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | ## Paywall Builder ile tasarlanan paywallın görünüm yapılandırmasını getirme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm yapılandırması getirilemez. ::: Paywallı getirdikten sonra, bunun Paywall Builder ile oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywallı nasıl görüntüleyeceğiniz konusunda size yol gösterecektir. `ViewConfiguration` mevcutsa, bunu Paywall Builder paywallı olarak değerlendirin; aksi takdirde [remote config paywallı olarak işleyin](present-remote-config-paywalls). Görünüm yapılandırmasını yüklemek için `getViewConfiguration` metodunu kullanın. ```kotlin showLineNumbers if (!paywall.hasViewConfiguration) { // use your custom logic return } AdaptyUI.getViewConfiguration(paywall, loadTimeout = 10.seconds) { result -> when(result) { is AdaptyResult.Success -> { val viewConfiguration = result.value // use loaded configuration } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` | Parametre | Zorunluluk | Açıklama | | :-------------- | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir. | Görünüm yapılandırmasını yüklemek için `getViewConfiguration` metodunu kullanın. ```java showLineNumbers if (!paywall.hasViewConfiguration()) { // use your custom logic return; } AdaptyUI.getViewConfiguration(paywall, TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyUI.LocalizedViewConfiguration viewConfiguration = ((AdaptyResult.Success) result).getValue(); // use loaded configuration } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesini](add-paywall-locale-in-adapty-paywall-builder) nasıl ekleyeceğinizi ve yerel ayar kodlarını doğru şekilde nasıl kullanacağınızı [buradan](android-localizations-and-locale-codes) öğrenin. ::: Yüklendikten sonra, [paywallı sunun](android-present-paywalls). ## Daha hızlı getirmek için varsayılan kitle paywallını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle paywalllar neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall göstermek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için paywallı getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Getirme](#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklanan `getPaywall` metoduyla paywallı getirmek olduğunu anlamak önemlidir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywalllarla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar, **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre) kaybettiğiniz anlamına gelir. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience` metodu Android SDK 2.11.3'ten itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi ise bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu yaklaşımı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.

| ## Varlıkları özelleştirme \{#customize-assets\} Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videoların önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Video başlamadan önce bir önizleme görseli gösterin. :::important Bu özelliği kullanmak için Adapty Android SDK'yı 3.7.0 veya daha yüksek bir sürüme güncelleyin. ::: Özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, customAssets, ) ``` :::note Bir varlık bulunamazsa, paywall varsayılan görünümüne geri döner. :::
--- # File: android-present-paywalls --- --- title: "Flow ve paywall'ları görüntüleme - Android" description: "Android uygulamanızda kullanıcılara flow ve paywall'ları sunun." --- Bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yok. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten barındırır. :::warning Bu kılavuz, Adapty tarafından render edilen flow'ları ve **yeni Paywall Builder paywalllarını** kapsar. Remote config paywallları ve [Observer mode](observer-vs-full-mode) için süreç farklıdır. - **Remote config paywall**'larını sunmak için bkz. [Remote config ile tasarlanmış paywall'ı göster](present-remote-config-paywalls). - **Observer mode paywall**'larını sunmak için bkz. [Android - Observer mode'da Paywall Builder paywall'larını sunma](android-present-paywall-builder-paywalls-in-observer-mode) ::: Aşağıda kullanılan `flowConfiguration` nesnesini almak için bkz. [Flow'ları ve paywall'ları al](android-get-pb-paywalls). Cihaz ekranında görsel flow'u görüntüleyebilmek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın veya `AdaptyFlowView`'ı doğrudan oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //gerekirse view hiyerarşisine ekleyin veya xml'den alın ... flowView.showFlow(flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra view hiyerarşisine ekleyebilir ve cihaz ekranında gösterebilirsiniz. `AdaptyFlowView`'ı `AdaptyUI.getFlowView()` çağrısı _yapmadan_ edinirseniz, ayrıca `.showFlow()` metodunu da çağırmanız gerekir. Görsel flow'u cihaz ekranında gösterebilmek için önce yapılandırmanız gerekir. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyFlowScreen( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------------------------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **flowConfiguration** | zorunlu | Flow'un görsel detaylarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi sağlayın. Yüklemek için `AdaptyUI.getFlowConfiguration(flow)` metodunu kullanın. Daha fazla bilgi için [Görünüm yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration) konusuna bakın. | | **products** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Flow olaylarını izlemek için bir `AdaptyFlowEventListener` sağlayın. Kullanım kolaylığı açısından `AdaptyFlowDefaultEventListener` sınıfını genişletmeniz önerilir. Daha fazla bilgi için [Flow ve paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı |

Inset'ler, tıklanabilir öğelerin sistem çubukların arkasına gizlenmesini önlemek için flow'un çevresindeki boşluklardır.

Varsayılan: `Unspecified` — yani Adapty inset'leri otomatik olarak ayarlar; bu, kenardan kenara flow'lar için idealdir.

Flow'unuz kenardan kenara değilse özel inset'ler ayarlamak isteyebilirsiniz. Bunun nasıl yapılacağını öğrenmek için aşağıdaki [Flow inset'lerini değiştirme](android-present-paywalls#change-flow-insets) bölümünü okuyun.

| | **customAssets** | isteğe bağlı | Flow veya paywall'ınızdaki görsel ve videoları çalışma zamanında değiştirmek için bir `AdaptyCustomAssets` nesnesi geçin. Daha fazla bilgi için [Varlıkları özelleştirme](android-get-pb-paywalls#customize-assets) konusuna bakın. | | **tagResolver** | isteğe bağlı | Flow metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve buna karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da özel etiketler konusuna bakın. | | **timerResolver** | isteğe bağlı | Özel zamanlayıcı işlevselliği kullanacaksanız çözümleyiciyi buraya geçin. | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Flow inset'lerini değiştirme \{#change-flow-insets\} Inset'ler, flow'un etrafındaki boşluklardır ve tıklanabilir öğelerin sistem çubuklarının arkasında gizlenmesini önler. Adapty varsayılan olarak inset'leri otomatik olarak ayarlar; bu, kenardan kenara flow'larda mükemmel çalışır. Flow'unuz kenardan kenara değilse, özel inset'ler ayarlamak isteyebilirsiniz: - `AdaptyFlowView` üst durum çubuğuyla da alt gezinme çubuğuyla da çakışmıyorsa `AdaptyFlowInsets.None` kullanın. - Flow'unuz üst durum çubuğuyla çakışıyor ancak altla çakışmıyorsa gibi daha özel durumlar için yalnızca `bottomInset` değerini aşağıdaki örnekte gösterildiği gibi `0` olarak ayarlayabilirsiniz: ```kotlin showLineNumbers //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view flowView.onReceiveSystemBarsInsets { insets -> val flowInsets = AdaptyFlowInsets.vertical(insets.top, 0) flowView.showFlow( flowConfiguration, products, eventListener, flowInsets, customAssets, tagResolver, timerResolver, ) } ``` ```java showLineNumbers ... ViewCompat.setOnApplyWindowInsetsListener(flowView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(flowView, null); AdaptyFlowInsets flowInsets = AdaptyFlowInsets.vertical(systemBarInsets.top, 0); flowView.showFlow(flowConfiguration, products, eventListener, flowInsets); return insets; }); ``` ## Geliştirici tanımlı zamanlayıcı kullanımı \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için bir `timerResolver` nesnesi oluşturun; bu nesne, özel zamanlayıcıları flow oluşturulduğunda yerlerine geçecek string değerlerle eşleştiren bir sözlük veya haritadır. İşte bir örnek: ```kotlin showLineNumbers ... val customTimers = mapOf( "CUSTOM_TIMER_NY" to Calendar.getInstance(TimeZone.getDefault()).apply { set(2025, 0, 1) }.time, // New Year 2025 ) val timerResolver = AdaptyUiTimerResolver { timerId -> customTimers.getOrElse(timerId, { Date(System.currentTimeMillis() + 3600 * 1000L) /* in 1 hour */ } ) } ``` ```java showLineNumbers ... Map customTimers = new HashMap<>(); customTimers.put( "CUSTOM_TIMER_NY", new Calendar.Builder().setTimeZone(TimeZone.getDefault()).setDate(2025, 0, 1).build().getTime() ); AdaptyUiTimerResolver timerResolver = new AdaptyUiTimerResolver() { @NonNull @Override public Date timerEndAtDate(@NonNull String timerId) { Date date = customTimers.get(timerId); return date != null ? date : new Date(System.currentTimeMillis() + 3600 * 1000L); /* in 1 hour */ } }; ``` Bu örnekte, `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı doğru değerle (örneğin `13d 09h 03m 34s` gibi — zamanlayıcının bitiş zamanından, yani Yılbaşı gibi bir tarihten, mevcut zamanın çıkarılmasıyla hesaplanan) dinamik olarak güncellemesini sağlar. ## Özel etiketleri kullanma \{#use-custom-tags\} Mobil uygulamanızda özel etiketler kullanmak için bir `tagResolver` nesnesi oluşturun; bu nesne, özel etiketleri flow oluşturulduğunda onların yerine geçecek string değerlerle eşleştiren bir sözlük ya da haritadır. İşte bir örnek: ```kotlin showLineNumbers val customTags = mapOf("USERNAME" to "John") val tagResolver = AdaptyUiTagResolver { tag -> customTags[tag] } ``` ```java showLineNumbers Map customTags = new HashMap<>(); customTags.put("USERNAME", "John"); AdaptyUiTagResolver tagResolver = customTags::get; ``` Bu örnekte, `USERNAME` Adapty kontrol panelinde `` olarak girdiğiniz özel bir etikettir. `tagResolver`, uygulamanızın bu özel etiketi dinamik olarak belirtilen değerle—örneğin `John`—değiştirmesini sağlar. `tagResolver`'ı flow'unuzu sunmadan hemen önce oluşturup doldurmanızı öneririz. Hazır olduğunda, flow'u sunmak için kullandığınız AdaptyUI metoduna iletin. ## Flow yükleme göstergesi rengini değiştirme \{#change-flow-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini aşağıdaki şekilde geçersiz kılabilirsiniz: ```xml showLineNumbers title = "XML" ```
Paywall Builder ile özelleştirilmiş bir paywall oluşturduysanız, kullanıcıya göstermek için mobil uygulama kodunuzda bu paywall'ı oluşturma konusunda endişelenmenize gerek yoktur. Böyle bir paywall, hem paywall içinde nelerin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz yalnızca SDK v3.0 gerektiren **yeni Paywall Builder paywallları** için geçerlidir. Paywall sunma süreci, farklı Paywall Builder sürümleriyle tasarlanan paywalllar, remote config paywalllar ve [Observer modu](observer-vs-full-mode) için farklılık gösterir. - **Remote config paywalllarını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls). - **Observer modu paywalllarını** sunmak için bkz. [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) ::: Aşağıda kullanılan `viewConfiguration` nesnesini almak için bkz. [Paywall Builder paywalllerini ve yapılandırmalarını getirme](android-get-pb-paywalls). Görsel paywall'ı cihaz ekranında göstermek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getPaywallView()` metodunu çağırın veya `AdaptyPaywallView`'i doğrudan oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //gerekirse görünüm hiyerarşisine ekleyin veya xml'den alın ... paywallView.showPaywall(viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver); ``` ```xml showLineNumbers ``` Görünüm başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyebilir ve cihaz ekranında gösterebilirsiniz. `AdaptyPaywallView`'ı `AdaptyUI.getPaywallView()` çağrısı _dışında_ bir yöntemle aldıysanız, `.showPaywall()` metodunu da çağırmanız gerekir. Görsel paywallı cihaz ekranında göstermek için önce yapılandırmanız gerekir. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :---------------------------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.LocalizedViewConfiguration` nesnesi sağlayın. Bunu yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywallın görsel yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **products** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı açısından AdaptyUiDefaultEventListener'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı |

Insets, tıklanabilir öğelerin sistem çubuklarının arkasına gizlenmesini önleyen paywall etrafındaki boşluklardır.

Varsayılan: `UNSPECIFIED` — bu, Adapty'nin inset'leri otomatik olarak ayarlayacağı anlamına gelir; bu ayar kenardan kenara paywalllar için mükemmel çalışır.

Paywallınız kenardan kenara değilse özel inset'ler ayarlamak isteyebilirsiniz. Bunun nasıl yapılacağını aşağıdaki [Paywall inset'lerini değiştirme](android-present-paywalls#change-paywall-insets) bölümünde okuyabilirsiniz.

| | **personalizedOfferResolver** | isteğe bağlı | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver` uygulayın ve `AdaptyPaywallProduct`'ı, ürünün fiyatı kişiselleştirilmişse `true`, değilse `false` olarak eşleyen kendi mantığınızı geçirin. | | **tagResolver** | isteğe bağlı | Paywall metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve bunu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'daki Özel Etiketler konusuna bakın. | | **timerResolver** | isteğe bağlı | Özel zamanlayıcı işlevselliği kullanacaksanız çözümleyiciyi buraya geçirin. | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Paywall insets'lerini değiştirme \{#change-paywall-insets\} Insets, tıklanabilir öğelerin sistem çubukları arkasında gizlenmesini engelleyen paywall etrafındaki boşluklardır. Varsayılan olarak Adapty, kenar-kenara paywalllar için harika çalışan insets'leri otomatik olarak ayarlar. Paywallınız kenar-kenara değilse özel insets ayarlamak isteyebilirsiniz: - `AdaptyPaywallView` ile ne durum çubuğu ne de gezinme çubuğu çakışmıyorsa `AdaptyPaywallInsets.NONE` kullanın. - Paywallınız üst durum çubuğuyla çakışıyor ama alt kısımla çakışmıyorsa gibi daha özel durumlarda, aşağıdaki örnekte gösterildiği gibi yalnızca `bottomInset`'i `0` olarak ayarlayabilirsiniz: ```kotlin showLineNumbers //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.vertical(insets.top, 0) paywallView.showPaywall( viewConfiguration, products, eventListener, paywallInsets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, 0); paywallView.showPaywall(paywall, products, viewConfiguration, paywallInsets, productTitleResolver); return insets; }); ``` ## Geliştirici tanımlı zamanlayıcı kullanma \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için bir `timerResolver` nesnesi oluşturun; bu nesne, özel zamanlayıcıları paywall oluşturulduğunda onların yerine geçecek string değerleriyle eşleştiren bir sözlük ya da haritadır. İşte bir örnek: ```kotlin showLineNumbers ... val customTimers = mapOf( "CUSTOM_TIMER_NY" to Calendar.getInstance(TimeZone.getDefault()).apply { set(2025, 0, 1) }.time, // New Year 2025 ) val timerResolver = AdaptyUiTimerResolver { timerId -> customTimers.getOrElse(timerId, { Date(System.currentTimeMillis() + 3600 * 1000L) /* in 1 hour */ } ) } ``` ```java showLineNumbers ... Map customTimers = new HashMap<>(); customTimers.put( "CUSTOM_TIMER_NY", new Calendar.Builder().setTimeZone(TimeZone.getDefault()).setDate(2025, 0, 1).build().getTime() ); AdaptyUiTimerResolver timerResolver = new AdaptyUiTimerResolver() { @NonNull @Override public Date timerEndAtDate(@NonNull String timerId) { Date date = customTimers.get(timerId); return date != null ? date : new Date(System.currentTimeMillis() + 3600 * 1000L); /* in 1 hour */ } }; ``` Bu örnekte, `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar; örneğin `13d 09h 03m 34s` (zamanlayıcının bitiş zamanı, Yeni Yıl günü gibi, eksi mevcut zaman olarak hesaplanır). ## Özel etiketleri kullanma \{#use-custom-tags\} Mobil uygulamanızda özel etiketler kullanmak için bir `tagResolver` nesnesi oluşturun; bu nesne, özel etiketleri paywall render edildiğinde onların yerini alacak dize değerleriyle eşleştiren bir sözlük veya haritadır. İşte bir örnek: ```kotlin showLineNumbers val customTags = mapOf("USERNAME" to "John") val tagResolver = AdaptyUiTagResolver { tag -> customTags[tag] } ``` ```java showLineNumbers Map customTags = new HashMap<>(); customTags.put("USERNAME", "John"); AdaptyUiTagResolver tagResolver = customTags::get; ``` Bu örnekte `USERNAME`, Adapty kontrol panelinde `` olarak girdiğiniz özel bir etikettir. `tagResolver`, uygulamanızın bu özel etiketi dinamik olarak belirtilen değerle (örneğin `John`) değiştirmesini sağlar. `tagResolver`'ı paywall'ı göstermeden hemen önce oluşturup doldurmanızı öneririz. Hazır olduğunda, paywall'ı sunmak için kullandığınız AdaptyUI metoduna aktarın. ## Yükleme göstergesinin rengini değiştirme \{#change-paywall-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini aşağıdaki şekilde geçersiz kılabilirsiniz: ```xml showLineNumbers title = "XML" ```
--- # File: android-handle-paywall-actions --- --- title: "Flow aksiyonlarına yanıt verme - Android" description: "Android uygulamanızda flow'lar ve paywall'lardan gelen buton aksiyonlarını yönetin." --- Adapty Flow Builder veya Paywall Builder kullanarak flow'lar veya paywall'lar oluşturuyorsanız, butonları doğru şekilde ayarlamak kritik öneme sahiptir: 1. [Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden tanımlanmış bir eylem atayın ya da özel bir eylem kimliği oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve önceden tanımlanmış eylemleri kodunuzda nasıl yöneteceğinizi gösterir. :::warning **Yalnızca satın almalar, yenileme işlemleri, flow/paywall kapatma ve URL açma otomatik olarak işlenir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun bir yanıt uygulaması gerektirir. ::: ## Flow ve paywallları kapatma \{#close-flows-and-paywalls\} Flow veya paywallınıza bir kapatma butonu eklemek için: 1. Builder'da bir buton ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda `close` eylemi için bir handler uygulayın. :::info Android SDK'da `close` eylemi, varsayılan olarak flow veya paywallı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda değiştirebilirsiniz. Örneğin, bir flow'un kapatılması başka bir flow'un açılmasını tetikleyebilir. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ## Flow ve paywalllardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde yönetin. ::: Flow veya paywallınızdan bir bağlantı açan bir düğme eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info Android SDK'da `openUrl` eylemi varsayılan olarak URL'yi açar. Ancak gerekirse bu davranışı kodunuzda değiştirebilirsiniz. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.OpenUrl -> { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(action.url)) // default behavior context.startActivity(intent) } } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yöneten bir buton eklemek için: 1. Builder'da bir buton ekleyin, ona **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi setiiniz veya tek seferlik satın almalarınız varsa, başka bir flow ya da paywall görüntüleyecek bir buton ekleyebilirsiniz: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Custom -> { if (action.customId == "openNewPaywall") { // Display another flow or paywall } } } } ``` Adapty paywall builder kullanarak paywall oluşturuyorsanız, düğmeleri doğru şekilde ayarlamak çok önemlidir: 1. [Paywall Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden var olan bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve önceden var olan eylemleri kodunuzda nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar, geri yüklemeler, paywall kapatmaları ve URL açma işlemleri otomatik olarak işlenir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun yanıt uygulaması gerektirir. ::: ## Paywallları kapatma \{#close-paywalls\} Paywallınızı kapatacak bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda, paywallı kapatan `close` eylemi için bir işleyici uygulayın. :::info Android SDK'da `close` eylemi, paywall'ı varsayılan olarak kapatır. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywallı kapatmak başka bir paywallın açılmasını tetikleyebilir. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle butonları işlediğiniz gibi yönetin. ::: Paywall'ınızdan bir bağlantı açan buton eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Paywall builder'da bir buton ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info Android SDK'da `openUrl` eylemi varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.OpenUrl -> { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(action.url)) // default behavior context.startActivity(intent) } } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` eylemi için bir işleyici uygulayın. ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Login -> { val intent = Intent(context, LoginActivity::class.java) context.startActivity(intent) } } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yönetecek bir düğme eklemek için: 1. Paywall Builder'da bir düğme ekleyin, **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, farklı bir abonelik teklifi grubunuz veya tek seferlik satın almalarınız varsa, başka bir paywall görüntüleyecek bir düğme ekleyebilirsiniz: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Custom -> { if (action.customId == "openNewPaywall") { // Display another paywall } } } } ``` --- # File: android-handling-events --- --- title: "Flow ve paywall olaylarını yönetme - Android" description: "Android uygulamanızda flow ve paywall olaylarını yönetin." --- :::important Bu kılavuz, satın alma, yenileme, ürün seçimi ve flow render işlemleri için event yönetimini kapsar. Ayrıca düğme işlemlerini de (flow'u kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini yönetme kılavuzumuza](android-handle-paywall-actions) bakın. ::: [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış flow'lar ve paywall'lar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak bu ekranlar, uygulamanızın yanıt verebileceği bazı olaylar üretir. Bu olaylar arasında buton tıklamaları (kapat butonları, URL'ler, ürün seçimleri vb.) ve satın alma işlemlerine ilişkin bildirimler yer alır. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız `AdaptyFlowEventListener` metodlarını uygulayın. Bazı durumlarda varsayılan davranışı korumak istiyorsanız, `AdaptyFlowDefaultEventListener` sınıfını genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz. Aşağıda `AdaptyFlowDefaultEventListener` içindeki varsayılan değerler yer almaktadır. ### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\} #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu method çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onProductSelected( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
#### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseStarted( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu metot Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olursa şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFinished( purchaseResult: AdaptyPurchaseResult, product: AdaptyPaywallProduct, context: Context, ) { if (purchaseResult !is AdaptyPurchaseResult.UserCanceled) context.getActivityOrNull()?.onBackPressed() } ```
Olay örnekleri (Genişletmek için tıklayın) ```javascript // Successful purchase { "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Cancelled purchase { "purchaseResult": { "type": "UserCanceled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Pending purchase { "purchaseResult": { "type": "Pending" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu durumda ekranı kapatmanızı öneririz. Bu metot, Observer modunda çağrılmayacaktır. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarısız satın alma \{#failed-purchase\} Bir satın alma işlemi hata nedeniyle başarısız olursa bu metot çağrılır. Bu durum; Google Play Billing hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptallerinin `onPurchaseFinished` metodunu iptal edilmiş sonuçla tetiklediğini, beklemedeki ödemelerin ise bu metodu tetiklemediğini unutmayın. ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFailure( error: AdaptyError, product: AdaptyPaywallProduct, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu yöntem, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllerini sunma](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu yöntem, belirli bir ürün için [web paywall](web-paywall) açma girişiminin ardından çağrılır. Hem başarılı hem de başarısız navigasyon girişimlerini kapsar: ```kotlin showLineNumbers title="Kotlin" public override fun onFinishWebPaymentNavigation( product: AdaptyPaywallProduct?, error: AdaptyError?, context: Context, ) {} ``` **Parametreler:** | Parametre | Açıklama | |:------------|:-------------------------------------------------------------------------------------------------------| | **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir. | | **error** | Web paywall navigasyonu başarısız olursa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. |
Etkinlik örnekleri (Genişletmek için tıklayın) ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_navigation_failed", "message": "Failed to open web paywall", "details": { "underlyingError": "Browser unavailable" } } } ```
#### Başarılı geri yükleme \{#successful-restore\} Bir satın alma başarıyla geri yüklenirse, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreSuccess( profile: AdaptyProfile, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ```
Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](android-listen-subscription-changes) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olursa, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreFailure( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
#### Abonelik yükseltme \{#upgrade-subscription\} Bir kullanıcı aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, bu metodu geçersiz kılarak yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. İki seçeneğiniz vardır: 1. **Mevcut aboneliği** yeni olanıyla değiştirin: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback, ): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived( AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) .build() ) return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` 2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle): ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyFlowEventListener.PurchaseParamsCallback, ): AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyFlowEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` :::note Bu yöntemi geçersiz kılmazsanız, varsayılan davranış her iki aboneliği de aktif tutmaktır (`AdaptyPurchaseParameters.Empty` kullanımıyla eşdeğer). ::: Gerekirse ek satın alma parametreleri de ayarlayabilirsiniz: ```kotlin AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // isteğe bağlı - mevcut aboneliği değiştirmek için .withOfferPersonalized(true) // isteğe bağlı - kişiselleştirilmiş fiyatlandırma kullanılıyorsa .build() ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_yearly", "localizedTitle": "Premium Yearly", "localizedDescription": "Premium subscription for 1 year", "localizedPrice": "$99.99", "price": 99.99, "currencyCode": "USD" }, "subscriptionUpdateParams": { "replacementMode": "with_time_proration" } } ```
### Veri getirme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürünleri iletmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir: ```kotlin showLineNumbers title="Kotlin" public override fun onLoadingProductsFailure( error: AdaptyError, context: Context, ): Boolean = false ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ```
`true` döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrarlar. #### Render hataları \{#rendering-errors\} Arayüz render edilirken bir hata oluşursa, bu metot çağrılarak raporlanır: ```kotlin showLineNumbers title="Kotlin" public override fun onError( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render flow interface", "details": { "underlyingError": "Invalid flow configuration" } } } ```
Normal koşullarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin. ### Gezinti \{#navigation\} #### Sistem geri düğmesi \{#system-back-button\} Varsayılan olarak, bir flow sistem geri düğmesiyle veya geri hareketiyle kapatılamaz — kullanıcı, flow'dan yalnızca sizin tanımladığınız bir yol aracılığıyla çıkar; örneğin bir **Close** düğmesi veya builder'daki bir `on_device_back` eylemi. Sistem geri düğmesinin flow'u kapatmasını istiyorsanız, `onBackPressed` metodunu geçersiz kılın ve ana activity'nizin ya da fragment'ınızın bu basışı işlemesine izin vermek için `false` döndürün: ```kotlin showLineNumbers title="Kotlin" public override fun onBackPressed(context: Context): Boolean { return false // let the host handle the back press (e.g. finish the activity or pop the fragment) } ``` Bu callback, yalnızca mevcut ekran için herhangi bir `on_device_back` eylemi yapılandırılmamışsa çağrılır — yapılandırılmış bir eylem öncelik alır ve dahili olarak işlenir. Geri tuşuna basma işlemini tüketmek için `true`, ana bileşenin kendi geri işleme mantığının çalışmasına izin vermek için `false` döndürün. ### Ayrılmış olaylar \{#reserved-events\} `AdaptyFlowEventListener`, flow'ların henüz kullanmadığı bazı işlevler için birkaç callback tanımlar. Bunları uygulamanıza gerek yok — `AdaptyFlowDefaultEventListener` zaten varsayılan olarak boş (no-op) uygulamalar sağlar. | Method | Description | |:-------|:------------| | **onAnalyticEvent** | Flow'lardan gelen özel analitik etkinlikler için ayrılmıştır. Flow'lar henüz bu etkinlikleri kodunuza iletmediğinden, bunu uygulamanıza gerek yoktur. | | **onShowAppRate** | Flow'lardan gelen uygulama değerlendirme istekleri için ayrılmıştır. Flow'lar henüz uygulama değerlendirme isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. | | **onShowRequestPermission** | Flow'lardan gelen sistem izin istekleri (push bildirimleri veya kamera erişimi gibi) için ayrılmıştır. Flow'lar henüz izin isteklerini tetiklemediğinden, bunu uygulamanıza gerek yoktur. |
:::important Bu kılavuz, satın almalar, geri yüklemeler, ürün seçimi ve paywall oluşturma için olay işlemeyi kapsar. Ayrıca düğme işlemeyi (paywallı kapatma, bağlantı açma vb.) de uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini işleme kılavuzumuza](android-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılan paywalllar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamaları (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili işlemlerin bildirimlerini kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. :::warning Bu kılavuz yalnızca Adapty SDK v3.0 veya üzerini gerektiren **yeni Paywall Builder paywallları** içindir. ::: :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: Satın alma ekranında gerçekleşen süreçleri kontrol etmek veya izlemek istiyorsanız `AdaptyUiEventListener` metodlarını uygulayın. Bazı durumlarda varsayılan davranışı korumak istiyorsanız `AdaptyUiDefaultEventListener`'ı genişletip yalnızca değiştirmek istediğiniz metodları override edebilirsiniz. Aşağıda `AdaptyUiDefaultEventListener`'daki varsayılan davranışlar yer almaktadır. ### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\} #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçilirse (kullanıcı tarafından veya sistem tarafından), bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onProductSelected( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
#### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseStarted( product: AdaptyPaywallProduct, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu metot, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywall'larını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olursa şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFinished( purchaseResult: AdaptyPurchaseResult, product: AdaptyPaywallProduct, context: Context, ) { if (purchaseResult !is AdaptyPurchaseResult.UserCanceled) context.getActivityOrNull()?.onBackPressed() } ```
Olay örnekleri (Genişletmek için tıklayın) ```javascript // Successful purchase { "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Cancelled purchase { "purchaseResult": { "type": "UserCanceled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Pending purchase { "purchaseResult": { "type": "Pending" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu durumda ekranı kapatmanızı öneririz. Bu metot, Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarısız satın alma \{#failed-purchase\} Bir satın alma işlemi hata nedeniyle başarısız olursa, bu method çağrılır. Buna Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları dahildir. Kullanıcı iptalleri yerine `onPurchaseFinished` methodunu iptal edilmiş sonucuyla tetiklediğini ve bekleyen ödemelerin bu methodu tetiklemediğini unutmayın. ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFailure( error: AdaptyError, product: AdaptyPaywallProduct, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
Bu metot Observer modunda çağrılmaz. Ayrıntılar için [Android - Observer modunda Paywall Builder paywalllarını gösterme](android-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu metot, belirli bir ürün için [web paywall](web-paywall) açma girişiminin ardından çağrılır. Başarılı ve başarısız navigasyon denemeleri için de çalışır: ```kotlin showLineNumbers title="Kotlin" public override fun onFinishWebPaymentNavigation( product: AdaptyPaywallProduct?, error: AdaptyError?, context: Context, ) {} ``` **Parametreler:** | Parametre | Açıklama | |:------------|:------------------------------------------------------------------------------------------------------------| | **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir. | | **error** | Web paywall navigasyonu başarısız olduysa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. |
Olay örnekleri (Genişletmek için tıklayın) ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_navigation_failed", "message": "Failed to open web paywall", "details": { "underlyingError": "Browser unavailable" } } } ```
#### Başarılı geri yükleme \{#successful-restore\} Bir satın alma işleminin geri yüklenmesi başarılı olursa, bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreSuccess( profile: AdaptyProfile, context: Context, ) {} ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ```
Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](android-listen-subscription-changes) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olursa, şu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreFailure( error: AdaptyError, context: Context, ) {} ```
Örnek olay (Genişletmek için tıklayın) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
#### Abonelik yükseltme \{#upgrade-subscription\} Bir kullanıcı, aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, bu metodu geçersiz kılarak yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. İki seçeneğiniz var: 1. **Mevcut aboneliği** yenisiyle değiştirin: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived( AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) .build() ) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` 2. **Her iki aboneliği de koru** (yenisini ayrı olarak ekle): ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` :::note Bu metodu override etmezseniz, varsayılan davranış her iki aboneliği de aktif tutmaktır (`AdaptyPurchaseParameters.Empty` kullanımına eşdeğer). ::: Gerekirse ek satın alma parametreleri de belirleyebilirsiniz: ```kotlin AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // isteğe bağlı - mevcut aboneliği değiştirmek için .withOfferPersonalized(true) // isteğe bağlı - kişiselleştirilmiş fiyatlandırma kullanılıyorsa .build() ``` Yeni bir abonelik satın alınırken mevcut bir abonelik hâlâ aktifse, geçerli aboneliği yenisiyle değiştirmek için bu metodu override edin. Aktif abonelik etkin kalmaya devam etmeli ve yeni abonelik ayrı olarak eklenmeliyse `onSubscriptionUpdateParamsReceived(null)` çağırın: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingSubscriptionUpdateParams( product: AdaptyPaywallProduct, context: Context, onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, ) { onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) } ```
Etkinlik örneği (Genişletmek için tıklayın) ```javascript { "product": { "vendorProductId": "premium_yearly", "localizedTitle": "Premium Yearly", "localizedDescription": "Premium subscription for 1 year", "localizedPrice": "$99.99", "price": 99.99, "currencyCode": "USD" }, "subscriptionUpdateParams": { "replacementMode": "with_time_proration" } } ```
### Veri çekme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Ürünleri başlatma sırasında geçirmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alacaktır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir: ```kotlin showLineNumbers title="Kotlin" public override fun onLoadingProductsFailure( error: AdaptyError, context: Context, ): Boolean = false ```
Örnek olay (Genişletmek için tıklayın) ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ```
`true` döndürürseniz, AdaptyUI isteği 2 saniye sonra tekrar eder. #### Render hataları \{#rendering-errors\} Arayüz render edilirken bir hata oluşursa, bu yöntem çağrılarak bildirilir: ```kotlin showLineNumbers title="Kotlin" public override fun onRenderingError( error: AdaptyError, context: Context, ) {} ```
Olay örneği (Genişletmek için tıklayın) ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ```
Normal koşullarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin.
--- # File: android-use-fallback-paywalls --- --- title: "Android - Yedek paywall'ları kullanma" description: "Kullanıcıların çevrimdışı olduğu veya Adapty sunucularının kullanılamadığı durumları yönetin." --- :::warning Yedek paywall'lar Android SDK v2.11 ve sonraki sürümlerde desteklenmektedir. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek yapılandırma dosyasını Android projenizin `assets` veya `res/raw` dizinine taşıyın. 2. Hedef flow, paywall veya onboarding'i getirmeden **önce** `.setFallback` metodunu çağırın. ```kotlin showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory val location = FileLocation.fromAsset("android_fallback.json") //or `FileLocation.fromAsset("/android_fallback.json")` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory val location = FileLocation.fromResId(context, R.raw.android_fallback) //you can also pass a file URI val fileUri: Uri = //get Uri for the file with fallback paywalls val location = FileLocation.fromFileUri(fileUri) //pass the file location Adapty.setFallback(location, callback) ``` ```java showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory FileLocation location = FileLocation.fromAsset("android_fallback.json"); //or `FileLocation.fromAsset("/android_fallback.json");` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory FileLocation location = FileLocation.fromResId(context, R.raw.android_fallback); //you can also pass a file URI Uri fileUri = //get Uri for the file with fallback paywalls FileLocation location = FileLocation.fromFileUri(fileUri); //pass the file location Adapty.setFallback(location, callback); ``` Parametreler: | Parametre | Açıklama | | :----------- | :----------------------------------------------------------- | | **location** | Yedek yapılandırma dosyası için [FileLocation](https://android.adapty.io/adapty/com.adapty.utils/-file-location/-companion/) nesnesi | --- # File: android-localizations-and-locale-codes --- --- title: "Android SDK'da yerelleştirme ve yerel ayar kodlarını kullanma" description: "Global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin (Android)." --- ## Bu neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır; örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywall'ı çekmeye çalışırken. Yerel ayar kodları karmaşık bir yapıya sahip olup platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlar için dahili bir standart kullanıyoruz. Ancak bu kodların karmaşıklığı nedeniyle, sunucumuza tam olarak ne gönderdiğinizi ve bundan sonra ne olacağını anlamanız son derece önemlidir; böylece her zaman beklediğiniz sonucu alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan yerel ayar koduyla birlikte bir çağrı aldığında ve bir paywall için karşılık gelen yerelleştirmeyi aramaya başladığında şunlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`), kısa çizgilerle (`-`) değiştirilir 2. Ardından tam olarak eşleşen yerel ayar koduna sahip yerelleştirme aranır 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesi döndürülür Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yol \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, büyük ihtimalle projenizde yerelleştirilmiş dize dosyalarıyla zaten çalışıyorsunuzdur. Bu durumda, her yerelleştirme için ilgili dosyalarınıza hedeflenen Adapty yerel ayar kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde kullanın: ```kotlin showLineNumbers // 1. Modify your strings.xml files /* strings.xml - Spanish */ es /* strings.xml - Portuguese (Brazil) */ pt-br // 2. Extract and use the locale code val localeCode = context.getString(R.string.adapty_paywalls_locale) // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yöntemle, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği üzerinde tam kontrol sahibi olursunuz. ## Yerelleştirmeleri uygulama: alternatif yol \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça yerel ayar kodları tanımlamadan benzer (ancak özdeş olmayan) sonuçlar elde edebilirsiniz. Bu, platforma ait başka nesnelerden yerel ayar kodu çıkarmak anlamına gelir: ```kotlin showLineNumbers val locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.resources.configuration.locales[0] else context.resources.configuration.locale val localeCode = locale.toLanguageTag() // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşımı önermiyoruz; çünkü Adapty sunucusunun tam olarak ne alacağını tahmin etmek güçtür. Yine de bu yaklaşımı kullanmaya karar verirseniz, tüm ilgili kullanım senaryolarını ele aldığınızdan emin olun. --- # File: android-web-paywall --- --- title: "Android SDK'da web paywall'larını uygulayın" description: "Play Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall'u ayarlayın." --- :::important Başlamadan önce [kontrol panelinde web paywall'unuzu yapılandırdığınızdan](web-paywall) ve Adapty SDK'nın 3.15 veya daha yeni bir sürümünü yüklediğinizden emin olun. ::: ## Web paywall'larını açma \{#open-web-paywalls\} Kendi geliştirdiğiniz bir paywall ile çalışıyorsanız, web paywall'larını SDK yöntemiyle ele almanız gerekir. `.openWebPaywall` yöntemi: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'u yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü takip eder ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` isteği gönderir. Bu sayede ödeme başarılı olmuş ve erişim hakları güncellenmiş ise abonelik uygulamada neredeyse anında etkinleşir. :::note Kullanıcılar uygulamaya döndükten sonra profil güncellemelerini yansıtmak için arayüzü yenileyin. Adapty, profil güncelleme olaylarını alıp işleyecektir. ::: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error } } ``` :::note `openWebPaywall` yönteminin iki versiyonu vardır: 1. Paywall'a göre URL oluşturan ve ürün verilerini de URL'lere ekleyen `openWebPaywall(product)`. 2. Paywall'a göre URL oluşturan ancak ürün verilerini URL'lere eklemeyen `openWebPaywall(paywall)`. Adapty paywall'undaki ürünler web paywall'undakilerden farklıysa bunu kullanın. ::: ## Uygulama içi tarayıcıda web paywall'larını açma \{#open-web-paywalls-in-an-in-app-browser\} Varsayılan olarak web paywall'lar harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sunmak için web paywall'larını uygulama içi tarayıcıda açabilirsiniz. Bu, web satın alma sayfasını uygulamanızın içinde göstererek kullanıcıların uygulama değiştirmeden işlemlerini tamamlamasına olanak tanır. Bunu etkinleştirmek için `presentation` parametresini `AdaptyWebPresentation.InAppBrowser` olarak ayarlayın: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, presentation = AdaptyWebPresentation.InAppBrowser, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error val adaptyError = error } } ``` --- # File: android-troubleshoot-paywall-builder --- --- title: "Android SDK'da Paywall Builder Sorunlarını Giderme" description: "Android SDK'da Paywall Builder sorunlarını giderme" --- Bu kılavuz, Android SDK'da Adapty Paywall Builder ile tasarlanmış paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `getViewConfiguration` metodu paywall yapılandırmasını alamıyor. **Neden**: Paywall Builder'da paywall'un cihazda görüntülenmesi etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. ## Paywall görüntüleme sayısı çok büyük \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntüleme sayısı beklenen değerin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (Android SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz; bu, Paywall Builder veya Flow Builder kullanıyorsanız görüntüleme sayısını çifte katlıyor. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitik otomatik olarak takip edilir, dolayısıyla bu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (Android SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder sorunlarıyla karşılaşıyorsunuz. **Çözüm**: Gerekirse [migration kılavuzlarını](android-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun daha yeni SDK sürümlerinde çözülmüştür. --- # File: android-quickstart-manual --- --- title: "Android SDK'da özel paywall'unuzda satın almaları etkinleştirin" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Android paywall'larınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall implementasyonunun tam kontrolü sizde kalırken Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler. :::important **Bu rehber, özel paywall'lar uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız [Adapty Flow Builder](android-quickstart-paywalls)'ı kullanın. Flow Builder ile no-code görsel editörde flow'lar oluşturursunuz, tüm satın alma mantığını Adapty otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlama \{#set-up-products\} Uygulama içi satın alımları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Products**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalls**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywall'lar aracılığıyla ulaşılabilir; bu tasarım sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. - [**Placements**](placements) – uygulamanızda paywall'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Paywall'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu yapı, A/B testleri çalıştırmayı ve farklı kullanıcılara farklı paywall'lar göstermeyi kolaylaştırır. Bu kavramları, özel paywallınızla çalışsanız bile anladığınızdan emin olun. Bunlar, uygulamanızda sattığınız ürünleri yönetmenin yollarından ibarettir. Özel paywallınızı hayata geçirmek için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu yapı, ürünlerinizi almanızı sağlar. Kontrol panelinde yapmanız gerekenleri anlamak için hızlı başlangıç kılavuzunu [buradan](quickstart) takip edin. ### Kullanıcıları yönetme \{#manage-users\} Kendi tarafınızda backend kimlik doğrulamasıyla veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve kimliği doğrulanmış kullanıcıları farklı şekilde yönetir. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik doğrulama hızlı başlangıç kılavuzunu](android-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywall'ınız için ürünleri almak üzere şunları yapmanız gerekir: 1. `getFlow` metoduna [placement](placements) ID'sini geçirerek `flow` nesnesini alın. 2. Bu flow için `getPaywallProducts` metodunu kullanarak ürünler dizisini alın. ```kotlin showLineNumbers fun loadPaywall() { Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value Adapty.getPaywallProducts(flow) { productResult -> when (productResult) { is AdaptyResult.Success -> { val products = productResult.value // Use products to build your custom paywall UI } is AdaptyResult.Error -> { val error = productResult.error // Handle the error } } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void loadPaywall() { Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); Adapty.getPaywallProducts(flow, productResult -> { if (productResult instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) productResult).getValue(); // Özel paywall UI'ınızı oluşturmak için ürünleri kullanın } else if (productResult instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) productResult).getError(); // Hatayı işleyin } }); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayı işleyin } }); } ``` ## Adım 2. Satın almaları kabul etme \{#step-2-accept-purchases\} Kullanıcı özel paywallınızda bir ürüne dokunduğunda, seçilen ürünle `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun purchaseProduct(activity: Activity, product: AdaptyPaywallProduct) { Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void purchaseProduct(Activity activity, AdaptyPaywallProduct product) { Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // Satın alma başarılı, profil güncellendi } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // Kullanıcı satın almayı iptal etti } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Satın alma beklemede (örn. kullanıcı nakit ile ödeyecek) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayı işle } }); } ``` ## 3. Adım: Satın almaları geri yükle \{#step-3-restore-purchases\} Google Play ve diğer uygulama mağazaları, abonelik sunan tüm uygulamaların kullanıcılara satın almalarını geri yükleyebilecekleri bir yol sunmasını zorunlu kılar. Kullanıcı geri yükle düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Restore successful, profile updated } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void restorePurchases() { Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // Geri yükleme başarılı, profil güncellendi } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Hatayla ilgilen } }); } ``` ## Sonraki adımlar :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywallınız uygulamada gösterilmeye hazır. Paywalldan test satın alımı tamamlayabildiğinizden emin olmak için [Google Play Store'da satın alımlarınızı test edin](testing-on-android). Bunun gerçek bir uygulamada nasıl çalıştığını görmek için örnek uygulamamızdaki [ProductListFragment.kt](https://github.com/adaptyteam/AdaptySDK-Android/blob/master/app/src/main/java/com/adapty/example/ProductListFragment.kt) dosyasına göz atın; bu dosya, hata yönetimi, kullanıcı arayüzü geri bildirimi ve abonelik yönetimi dahil olmak üzere satın alma işlemlerinin nasıl ele alındığını göstermektedir. Ardından, paywall'u gösterip göstermeyeceğinizi ya da ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın alma işlemini tamamlayıp tamamlamadığını kontrol edin](android-check-subscription-status). --- # File: fetch-paywalls-and-products-android --- --- title: "Android SDK'da remote config paywalllar için paywall ve ürün çekme" description: "Kullanıcı monetizasyonunu artırmak için Adapty Android SDK'da paywall ve ürün çekme." --- Remote config ve özel paywallları göstermeden önce bunlara ilişkin bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. **Flow Builder** veya **Paywall Builder** ile özelleştirilmiş flow'ları veya paywallları çekme hakkında rehberlik için lütfen [Flow'ları ve paywallları getir](android-get-pb-paywalls) sayfasına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. :::
Mobil uygulamanızda flow'ları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow ya da paywall'ınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-android).
## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonudur. Bu platformlar arası ürünler, flow'lara ve paywall'lara entegre edilerek belirli mobil uygulama placement'larında sergilenebilir. Ürünleri göstermek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini hardcode etmeyin.** Hardcode etmeniz gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir flow bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // istenen flow } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. || **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir; ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli aralıklarla güncellendiğinden, oturum sırasında gereksiz ağ isteklerini önlemek amacıyla güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.

Adapty SDK, flow'ları ve paywall'ları iki katmanda depolar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywall'lar](android-use-fallback-paywalls). Ayrıca flow'ları ve paywall'ları daha hızlı getirmek için CDN, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanırız.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbellekteki veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

| Ürün ID'lerini kodunuza sabit olarak yazmayın! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme süresi gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Kodunuza sabit olarak yazmanız gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, `remoteConfigs` dizisi (yapılandırılmış her yerel ayar için bir giriş) ve `hasViewConfiguration` bayrağını içeren bir `AdaptyFlow` nesnesi. Flow için ürünleri almak üzere `getPaywallProducts(flow)` çağrısını kullanın. | :::note v4'te `locale` parametresi `getFlow`'dan `getFlowConfiguration`'a taşındı (yalnızca AdaptyUI ile render ederken kullanılır). Özel paywalllar için mevcut tüm locale'ler `flow.remoteConfigs` içinde birlikte döndürülür; kullanıcının cihaz diline veya uygulamanızın ayarına uygun locale'i seçin. ::: ## Ürünleri getir \{#fetch-products\} Flow'a sahip olduktan sonra, o flow'a karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(flow) { result -> when (result) { is AdaptyResult.Success -> { val products = result.value // the requested products } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallProducts(flow, result -> { if (result instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) result).getValue(); // istenen ürünler } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnelerinin listesi: ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler. | Kendi flow tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesindeki bu özelliklere erişmeniz muhtemelen gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı dokümana bakın. | Özellik | Açıklama | |----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin cihazın yerel ayarına değil, kullanıcının mağazada seçtiği ülkeye göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Fiyata sayı olarak erişmek için `product.price.amount` özelliğini kullanabilirsiniz; değer yerel para biriminde döner. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (hafta, ay, yıl vb.) göstermek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Buradan `unit` enum değerine ulaşarak dönem uzunluğunu alabilirsiniz (DAY, WEEK, MONTH, YEAR veya UNKNOWN). `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini rozet veya başka bir gösterge ile belirtmek için `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu kullanışlı özellikler yer alır:
• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerine sahip bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.
• `price`: İndirimli fiyatı sayı olarak verir. Ücretsiz denemeler için bu değer `0` olur.
• `localizedNumberOfPeriods`: Teklifin uzunluğunu cihazın yerel ayarına göre biçimlendirilmiş bir string olarak gösterir. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` şeklinde görünür.
• `subscriptionPeriod`: Teklif döneminin ayrıntılarına tek tek erişmek için bu özelliği kullanabilirsiniz. Abonelikler için açıklanan önceki bölümle aynı şekilde çalışır.
• `localizedSubscriptionPeriod`: İndirimin abonelik dönemini kullanıcının yerel ayarına göre biçimlendirilmiş olarak döndürür. | ## Varsayılan kitle flow'u ile flow getirmeyi hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız olduğunda ve kullanıcılarınızın internet bağlantısı zayıf olduğunda, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow'unu getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak kritik önem taşır: önerilen yaklaşım, yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-android#fetch-flow-information) bölümünde ayrıntılandırıldığı gibi `getFlow` metoduyla flow'u getirmektir. :::warning `getFlow` kullanımını neden öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecek) farklı flow'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamak ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşabileceğini kabul etmek zorunda kalırsınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize göre hedefleme dahil) kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı flow getirme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-android#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value // the requested flow } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); // istenen flow } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. || **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Bu seçeneği öneririz çünkü kullanıcılarınızın her zaman en güncel verilere erişmesini sağlar.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu durumda kullanıcılar en son verileri alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.

|
Remote config ve özel paywallları sergilemeye başlamadan önce, bunlarla ilgili bilgileri getirmeniz gerekiyor. Bu konunun remote config ve özel paywalllar ile ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları getirme konusunda rehberlik için lütfen [Paywall Builder paywalllarını ve yapılandırmalarını getirme](android-get-pb-paywalls) sayfasına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. :::
Mobil uygulamanızda paywallları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın) 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. [Bir paywall oluşturun ve ürünlerinizi paywall'unuza ekleyin](create-paywall) Adapty Kontrol Paneli'nde. 3. [Placement'lar oluşturun ve paywall'unuzu placement'a ekleyin](create-placement) Adapty Kontrol Paneli'nde. 4. [Adapty SDK'yı yükleyin](sdk-installation-android) mobil uygulamanıza.
## Paywall bilgilerini getirme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonunu temsil eder. Bu platformlar arası ürünler, belirli mobil uygulama placement'larında sergilenebilmesi için paywall'lara entegre edilir. Ürünleri gösterebilmek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan yazmanız gereken tek ID, placement ID'sidir. Paywall'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir paywall bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // istenen paywall } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // istenen paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi ise bölge içindir.

Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa önbellekten döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla güvenle kullanılabilir.

Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında temizlendiğini unutmayın.

Adapty SDK, paywall'ları iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](android-use-fallback-paywalls). Paywall'ların daha hızlı getirilmesi için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garanti edecek şekilde tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür.

Nadir durumlarda bu metodun `loadTimeout` içinde belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.

| Ürün ID'lerini hardcode etmeyin! Paywall'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zamanla değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Hardcode etmeniz gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün kimliklerinin listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | ## Ürünleri getir \{#fetch-products\} Paywall'a sahip olduktan sonra, buna karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall) { result -> when (result) { is AdaptyResult.Success -> { val products = result.value // the requested products } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallProducts(paywall, result -> { if (result instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) result).getValue(); // istenen ürünler } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // hatayı işle } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnelerinin listesi; ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içerir. | Kendi paywall tasarımınızı uygularken, büyük ihtimalle [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın. | Özellik | Açıklama | |------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın dil ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın dil bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz; değer yerel para birimi cinsinden döner. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (hafta, ay, yıl vb.) göstermek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın dil ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Buradan `unit` enum'una erişerek süreyi (DAY, WEEK, MONTH, YEAR veya UNKNOWN) alabilirsiniz. `numberOfUnits` değeri ise dönem birimlerinin sayısını verir. Örneğin üç aylık bir abonelikte `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu yararlı özellikler yer alır:
• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerine sahip bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.
• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemelerde bu değer `0` olur.
• `localizedNumberOfPeriods`: Cihazın dil ayarına göre yerelleştirilmiş, teklifin süresini açıklayan bir metin. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak gösterilir.
• `subscriptionPeriod`: Teklif döneminin ayrıntılı bilgisini almak için bu özelliği kullanabilirsiniz; önceki bölümde abonelikler için açıklanan şekilde çalışır.
• `localizedSubscriptionPeriod`: Kullanıcının dil ayarına göre biçimlendirilmiş, indirim için abonelik dönemi metni. | ## Varsayılan kitle paywallı ile paywall getirmeyi hızlandırın \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywalliniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için paywall'ı çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Paywall Bilgisini Çekme](fetch-paywalls-and-products-android#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywall'ı çekmek olduğunu anlamanız kritik önem taşır. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekirse zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywall'larla sorun yaşamasını kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul edip daha hızlı paywall yükleme avantajından faydalanmak istiyorsanız, `getPaywallForDefaultAudience` yöntemini aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-android#fetch-paywall-information) açıklanan `getPaywall` yöntemini kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // istenen paywall } is AdaptyResult.Error -> { val error = result.error // hatayı işle } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience` metodu Android SDK 2.11.3 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirlediğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.

Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve kullanım önerilerimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](android-localizations-and-locale-codes) bölümüne bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar her zaman en güncel veriye ulaşamayabilir; ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için güvenle kullanılabilir.

Önbelleğin, uygulama yeniden başlatıldığında korunduğunu; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını unutmayın.

|
--- # File: present-remote-config-paywalls-android --- --- title: "Android SDK'da remote config ile tasarlanan paywallı render etme" description: "Adapty Android SDK'da remote config paywalllarını nasıl sunacağınızı keşfedin ve kullanıcı deneyimini kişiselleştirin." --- Remote config ile bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulama kodunuzda render işlemini kendiniz uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini siz belirlersiniz. Adapty, remote config'i çekmeniz için bir metot sağlar; özel paywallınızı nasıl göstereceğiniz tamamen size kalmıştır. ## Flow remote config'i alın ve sunun \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` dizisindeki yapılandırılmış her locale için bir `AdaptyRemoteConfig` girdisi taşır. Kullanıcının tercihiyle eşleşen locale'i seçin, ardından ihtiyacınız olan değerleri okuyun. ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val flow = result.value val config = flow.remoteConfigs.firstOrNull { it.locale == "en" } ?: flow.remoteConfigs.firstOrNull() val headerText = config?.dataMap?.get("header_text") as? String } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyFlow flow = ((AdaptyResult.Success) result).getValue(); AdaptyRemoteConfig config = null; for (AdaptyRemoteConfig remoteConfig : flow.getRemoteConfigs()) { if ("en".equals(remoteConfig.getLocale())) { config = remoteConfig; break; } } if (config == null && !flow.getRemoteConfigs().isEmpty()) { config = flow.getRemoteConfigs().get(0); } if (config != null && config.getDataMap().get("header_text") instanceof String) { String headerText = (String) config.getDataMap().get("header_text"); } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil ekranlarını ve yönlerini desteklediğinden emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunabilirsiniz. :::warning Adapty analitiğinin huni ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde [paywall görüntüleme etkinliğini kaydedin](present-remote-config-paywalls-android#track-paywall-view-events). ::: Paywallı görüntüledikten sonra satın alma akışını ayarlamaya devam edin. Kullanıcı bir satın alma işlemi yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](android-making-purchases) bölümünü okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](android-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellekte veri bulunmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme olaylarını izleyin \{#track-paywall-view-events\} Adapty, flow'larınızın ve paywall'larınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplasak da, görüntüleme olaylarını kaydetmek için sizin müdahaleniz gerekir; çünkü bir kullanıcının flow'u ne zaman gördüğünü yalnızca siz bilirsiniz. Bir görüntüleme olayı kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterlidir; bu olay, dönüşüm hunileri ve A/B testlerindeki metriklerinize yansıyacaktır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow veya paywallları görüntülüyorsanız `.logShowFlow(flow)` çağrısına gerek yoktur. Adapty bu durumlarda görüntülemeleri otomatik olarak takip eder. ::: ```kotlin showLineNumbers Adapty.logShowFlow(flow) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :-------- | :------- |:-----------------------------------------------------------------------------------------| | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla alınan bir `AdaptyFlow` nesnesi. | Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın koduna render işlemini eklemeniz gerekir. Remote config, ihtiyaçlarınıza göre şekillendirilmiş bir esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini tamamen siz belirlersiniz. Remote config aracılığıyla yapılandırdığınız özel paywall'ı göstermek için remote configuration'ı çeken bir metot sunuyoruz. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri oradan çekin. ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); AdaptyPaywall.RemoteConfig remoteConfig = paywall.getRemoteConfig(); if (remoteConfig != null) { if (remoteConfig.getDataMap().get("header_text") instanceof String) { String headerText = (String) remoteConfig.getDataMap().get("header_text"); } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Gerekli tüm değerleri aldıktan sonra, bunları görsel açıdan çekici bir sayfaya dönüştürme zamanı gelmiştir. Tasarımın farklı ekran boyutlarına ve yönlendirmelerine uyum sağladığından emin olun; böylece kullanıcılara her cihazda sorunsuz ve kullanışlı bir deneyim sunabilirsiniz. :::warning Aşağıda açıklandığı gibi [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-android#track-paywall-view-events) emin olun; bu sayede Adapty analitiği huni ve A/B testi veilerini doğru şekilde toplayabilir. ::: Paywallı gösterdikten sonra satın alma akışını kurarak devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](android-making-purchases) bölümünü inceleyin. [Yedek paywall olarak bir fallback paywall oluşturmanızı](android-use-fallback-paywalls) öneririz. Bu yedek paywall, internet bağlantısı olmadığında veya önbellekte veri bulunmadığında kullanıcıya gösterilir ve her koşulda kesintisiz bir deneyim sağlar. ## Paywall görüntüleme olaylarını kaydedin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın almaları otomatik olarak takip etsek de, paywall görüntülemelerini kaydetmek için sizin müdahaleniz gerekir; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu olay huni ve A/B testi metriklerinize yansıyacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywallları gösteriyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:---------------------------------------------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesi. | --- # File: android-making-purchases --- --- title: "Android SDK'da mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın alma ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'ları yalnızca göstermek, satın almaları desteklemek için yeterlidir; bu yalnızca paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullandığınızda geçerlidir. Paywall Builder kullanmıyorsanız satın almayı tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime geçmesini ve istedikleri işlemleri gerçekleştirmesini sağlayan ana yoldur. Paywall'ınızda kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa, Adapty bunu satın alma sırasında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik olarak uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın. Diğer durumlarda [kullanıcının iOS'ta başlangıç teklifine uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlamak uygulamanızın yayın sırasında reddedilmesine yol açabilir. Ayrıca başlangıç teklifine hak kazanmış kullanıcıların tam fiyat üzerinden ücretlendirilmesine neden olabilir. ::: Tek bir adımı bile atlamadan [başlangıç yapılandırmasını](quickstart) tamamladığınızdan emin olun. Bu olmadan satın almaları doğrulayamayız. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir—bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlamıyla uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](android-implement-paywalls-manually) göz atın. ::: ```kotlin showLineNumbers Adapty.makePurchase(activity, product, null) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` ```java showLineNumbers Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // Grant access to the paid features } } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // Handle the case where the user canceled the purchase } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Handle deferred purchases (e.g., the user will pay offline with cash) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- | :----------------------------------------------------------------------------------------------- | | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.

Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için access level durumunu kontrol edin.

| :::warning **Not:** Apple'ın StoreKit sürümü v2.0'dan düşük ve Adapty SDK sürümü v2.9.0'dan düşükse, bunun yerine [Apple App Store paylaşımlı sırrı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem Apple tarafından artık kullanım dışı bırakılmıştır. ::: ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu işlemin nasıl çalışacağı uygulama mağazasına göre değişir. Google Play'de abonelik otomatik olarak güncellenmez. Geçişi aşağıda açıklandığı şekilde mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka bir abonelikle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```kotlin showLineNumbers Adapty.makePurchase( activity, product, AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build() ) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :--------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | zorunlu | Bir [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) nesnesi. | ```java showLineNumbers Adapty.makePurchase( activity, product, new AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build(), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // successful cross-grade } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // user canceled the purchase flow } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // the purchase has not been finished yet, e.g. user will pay offline by cash } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :--------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | zorunlu | Bir [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) nesnesi. | Abonelikler ve değiştirme modları hakkında daha fazla bilgiyi Google Geliştirici belgelerinde okuyabilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Değiştirme modları için Google önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değiştirme modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: Bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değiştirme modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik faturalama dönemi sona erdiğinde gerçekleşir. ### Ön ödemeli planları yönetme \{#manage-prepaid-plans\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin birkaç aylık yenilenmez abonelik satın alma), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build(); ``` --- # File: android-restore-purchase --- --- title: "Android SDK'da mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz kullanıcı deneyimi sağlamak için Adapty'de satın almaları nasıl geri yükleyeceğinizi öğrenin." --- Satın Almaları Geri Yükleme, kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden erişmesini sağlayan bir özelliktir. Bu özellik, uygulamayı silip yeniden yükleyen ya da yeni bir cihaza geçip daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça faydalıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywallerde, satın almalar sizin tarafınızdan ek bir kod yazılmasına gerek kalmadan otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz. ::: Paywalli özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almayı geri yüklemek için `.restorePurchases()` metodunu çağırın: ```kotlin showLineNumbers Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); if (profile != null) { AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // successful access restore } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------| | **Profile** |

Bir [`AdaptyProfile`](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi. Bu model, access level, abonelik ve abonelik dışı satın alma bilgilerini içerir.

Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level durumunu** kontrol edin.

| :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: implement-observer-mode-android --- --- title: "Android SDK'da Observer modunu uygulama" description: "Android SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve Adapty'ye tam geçişe hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer Modu, gelişmiş analitik ve attribution ile analitik sistemleriyle sorunsuz entegrasyon sunar. Bu sizin için yeterliyse yapmanız gerekenler: 1. `observerMode` parametresini `true` olarak ayarlayarak Adapty SDK'yı yapılandırırken Observer modunu açın. [Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk) için kurulum talimatlarını takip edin. 2. Mevcut satın alma altyapınızdan Adapty'ye [işlemleri bildirin](report-transactions-observer-mode-android). ## Observer modu kurulumu \{#observer-mode-setup\} Satın almaları ve abonelik durumunu kendiniz yönetiyorsanız ve abonelik olayları ile analitik göndermek için Adapty kullanıyorsanız Observer modunu açın. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle bunu kendiniz yönettiğinizden emin olun. ::: ```kotlin showLineNumbers class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ) } ``` ```java showLineNumbers public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ); } ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden boolean değer. Varsayılan değer `false`'tur. | ## Observer Modunda Adapty paywalllarını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywalllarını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer modunda biraz ek kurulum gerektirir. Yukarıdaki adımlara ek olarak yapmanız gerekenler: 1. [Remote config paywallları](present-remote-config-paywalls-android) için paywallları her zamanki gibi görüntüleyin. Paywall Builder paywallları için [Android](android-present-paywall-builder-paywalls-in-observer-mode)'a özel kurulum kılavuzlarını takip edin. 3. Satın alma işlemleriyle [paywallları ilişkilendirin](report-transactions-observer-mode-android). --- # File: report-transactions-observer-mode-android --- --- title: "Android SDK'da Observer Mode'da işlemleri raporlama" description: "Android SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini raporlayın." --- Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan gelen işlemleri kendiniz raporlamanız gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız çok önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanın. :::warning **İşlem raporlamayı atlamayın!** `reportTransaction` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywallları kullanıyorsanız, işlemi raporlarken `variationId` bilgisini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```kotlin showLineNumbers val transactionInfo = TransactionInfo.fromPurchase(purchase) Adapty.reportTransaction(transactionInfo, variationId) { result -> if (result is AdaptyResult.Success) { // success } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | ---------------------------------------------------------- | | transactionInfo | zorunlu | Satın almadan elde edilen TransactionInfo; buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java showLineNumbers TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); Adapty.reportTransaction(transactionInfo, variationId, result -> { if (result instanceof AdaptyResult.Success) { // success } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | ---------------------------------------------------------- | | transactionInfo | zorunlu | Satın almadan elde edilen TransactionInfo; buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan gelen işlemleri raporlamanız ya da geri yüklemeniz gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız çok önemlidir. İşlemi Adapty'ye raporlamak için `restorePurchases` kullanın. :::warning **Satın alma geri yüklemeyi atlamayın!** `restorePurchases` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywallları kullanıyorsanız, `setVariationId` metoduyla işleminizi satın almaya yol açan paywall ile ilişkilendirin. Bu, satın almanın tetikleyen paywall'a doğru şekilde atfedilmesini ve analizlerin doğru olmasını sağlar. Bu adım yalnızca Adapty paywalllarını kullanıyorsanız gereklidir. ```kotlin showLineNumbers Adapty.restorePurchases { result -> if (result is AdaptyResult.Success) { // success } } Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (`purchase.getOrderId`); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { // success } }); Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (`purchase.getOrderId`); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | **İşlemleri raporlama** Observer Mode'da Adapty'ye işlem raporlamak için `restorePurchases` kullanın. Ayrıntılar için [Mobil Kodda Satın Alma Geri Yükleme](android-restore-purchase) sayfasına bakın. :::warning **İşlem raporlamayı atlamayın!** `restorePurchases` çağrılmazsa Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: **Paywallları işlemlerle ilişkilendirme** Adapty SDK, satın almaları siz yönettiğiniz için satın alma kaynağını belirleyemez. Bu nedenle Observer mode'da paywallları ve/veya A/B testlerini kullanmayı planlıyorsanız, app store'dan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Uygulamanızı yayınlamadan önce bunu doğru şekilde yapılandırmanız önemlidir; aksi hâlde analizlerde hatalara yol açar. ```kotlin Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (purchase.getOrderId); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | ```java Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` | Parametre | Zorunluluk | Açıklama | | ------------------------------------------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | Satın almanın string tanımlayıcısı (purchase.getOrderId); buradaki satın alma, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir. | | variationId | zorunlu | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | --- # File: android-present-paywall-builder-paywalls-in-observer-mode --- --- title: "Android SDK'da Observer mode'da Paywall Builder paywalllarını sunma" description: "Adapty'nin Paywall Builder'ını kullanarak observer mode'da paywallları nasıl sunacağınızı öğrenin." --- Flow Builder veya Paywall Builder kullanarak bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etmeniz konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. :::warning Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız bunun yerine [Android - Flow ve paywall'ları gösterme](android-present-paywalls) konusuna bakın. :::
Flow'ları göstermeye başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play ile](initial-android) başlangıç entegrasyonunu yapın. 2. Adapty SDK'yı yükleyip yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza [Android için](sdk-installation-android) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'lar veya paywall'lar yapılandırın](create-paywall) ve ürünleri bunlara atayın. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow'larınızı ya da paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını alın](android-get-pb-paywalls).

1. `AdaptyUiObserverModeHandler`'ı uygulayın. `onPurchaseInitiated` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu callback'e yanıt olarak özel satın alma flow'unuzu tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, flow, flowView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, flow, flowView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Observer mode'da geri yüklemeleri yönetmek için `getRestoreHandler()` metodunu geçersiz kılın. Varsayılan olarak `null` döndürür; bu durumda Adapty'nin yerleşik `Adapty.restorePurchases()` flow'u kullanılır. Kendi geri yükleme implementasyonunuzu sağlamak için: ```kotlin showLineNumbers val observerModeHandler = object : AdaptyUiObserverModeHandler { // onPurchaseInitiated implementation (see above) override fun getRestoreHandler() = AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore -> onStartRestore() yourBillingClient.restorePurchases( onSuccess = { restoredPurchases -> onFinishRestore() //handle successful restore }, onError = { onFinishRestore() //handle error } ) } } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() { // onPurchaseInitiated implementation (see above) @Override public RestoreHandler getRestoreHandler() { return (onStartRestore, onFinishRestore) -> { onStartRestore.invoke(); yourBillingClient.restorePurchases( restoredPurchases -> { onFinishRestore.invoke(); //handle successful restore }, error -> { onFinishRestore.invoke(); //handle error } ); }; } }; ``` AdaptyUI'yı satın alma veya geri yükleme işlemi hakkında bilgilendirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi doğru flow davranışı için gereklidir: | Callback | Açıklama | | :----------------- |:--------------------------------------------------------------------------------------------------| | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için çağrılması gereken callback. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için çağrılması gereken callback. | | onStartRestore() | İsteğe bağlı. Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için çağrılabilecek callback. | | onFinishRestore() | İsteğe bağlı. Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için çağrılabilecek callback. | 2. Flow'u cihaz ekranında görüntülemek için önce yapılandırmanız gerekir. Bunun için `AdaptyUI.getFlowView()` metodunu çağırın veya `AdaptyFlowView`'i doğrudan oluşturun: ```kotlin showLineNumbers val flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) ``` ```kotlin showLineNumbers val flowView = AdaptyFlowView(activity) // or retrieve it from xml ... with(flowView) { showFlow( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) } ``` ```java showLineNumbers AdaptyFlowView flowView = AdaptyUI.getFlowView( activity, flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler ); ``` ```java showLineNumbers AdaptyFlowView flowView = new AdaptyFlowView(activity); //add to the view hierarchy if needed, or you receive it from xml ... flowView.showFlow(flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, onu view hiyerarşisine ekleyebilir ve görüntüleyebilirsiniz. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyFlowScreen( flowConfiguration, products, eventListener, insets, customAssets, tagResolver, timerResolver, observerModeHandler, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **flowConfiguration** | zorunlu | Flow'un görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi sağlayın. Yüklemek için `AdaptyUI.getFlowConfiguration(flow)` metodunu kullanın. Daha fazla bilgi için [Görünüm yapılandırmasını getir](android-get-pb-paywalls#fetch-the-view-configuration) konusuna bakın. | | **products** | isteğe bağlı | Ürünlerin ekranda gösterilme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **eventListener** | isteğe bağlı | Flow olaylarını izlemek için bir `AdaptyFlowEventListener` sağlayın. Kullanım kolaylığı açısından `AdaptyFlowDefaultEventListener` sınıfını genişletmeniz önerilir. Daha fazla bilgi için [Flow ve paywall olaylarını yönet](android-handling-events) konusuna bakın. | | **insets** | isteğe bağlı | Insets, tıklanabilir öğelerin sistem çubuklarının arkasına gizlenmesini önlemek için flow'un etrafındaki boşluklardır. Varsayılan: `Unspecified`; bu değer Adapty'nin insets'leri otomatik olarak ayarlamasına izin verir. Bkz. [Flow insets'lerini değiştir](android-present-paywalls#change-flow-insets). | | **customAssets** | isteğe bağlı | Çalışma zamanında flow veya paywall'unuzdaki görsel ve videoları değiştirmek için bir `AdaptyCustomAssets` nesnesi geçirin. Daha fazla bilgi için [Varlıkları özelleştir](android-get-pb-paywalls#customize-assets) konusuna bakın. | | **tagResolver** | isteğe bağlı | Flow metni içindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve onu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **observerModeHandler** | Observer mode için zorunlu | Bir önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | :::warning Satın alma işlemlerini [paywall'larla ilişkilendirmeyi](report-transactions-observer-mode-android) unutmayın. Aksi takdirde, Adapty satın almanın kaynak flow'unu belirleyemez. :::
Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu kurun. 2. Adapty SDK'yı yükleyip yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza [Android için](sdk-installation-android) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri onlara atayın](create-paywall) ve Paywall Builder ile özelleştirin. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını getirin](android-get-pb-paywalls).

1. `AdaptyUiObserverModeHandler`'ı uygulayın. `onPurchaseInitiated` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu callback'e yanıt olarak özel satın alma flow'unuzu tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Observer mode'da restore işlemlerini yönetmek için `getRestoreHandler()` metodunu override edin. Varsayılan olarak `null` döndürür; bu durumda Adapty'nin yerleşik `Adapty.restorePurchases()` flow'u kullanılır. Kendi restore implementasyonunuzu sağlamak için: ```kotlin showLineNumbers val observerModeHandler = object : AdaptyUiObserverModeHandler { // onPurchaseInitiated implementation (see above) override fun getRestoreHandler() = AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore -> onStartRestore() yourBillingClient.restorePurchases( onSuccess = { restoredPurchases -> onFinishRestore() //handle successful restore }, onError = { onFinishRestore() //handle error } ) } } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() { // onPurchaseInitiated implementation (see above) @Override public RestoreHandler getRestoreHandler() { return (onStartRestore, onFinishRestore) -> { onStartRestore.invoke(); yourBillingClient.restorePurchases( restoredPurchases -> { onFinishRestore.invoke(); //handle successful restore }, error -> { onFinishRestore.invoke(); //handle error } ); }; } }; ``` Ödeme veya geri yükleme sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi paywall'un düzgün çalışması için gereklidir: | Callback | Açıklama | | :----------------- |:-------------------------------------------------------------------------------------------------------| | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | İsteğe bağlı. Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılabilir. | | onFinishRestore() | İsteğe bağlı. Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılabilir. | 2. Görsel paywallı cihaz ekranında görüntülemek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getPaywallView()` metodunu çağırın ya da doğrudan `AdaptyPaywallView` oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.showPaywall(viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler); ``` ```xml showLineNumbers ``` View başarıyla oluşturulduktan sonra, onu view hiyerarşisine ekleyebilir ve görüntüleyebilirsiniz. Bunun için şu composable fonksiyonu kullanın: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **Products** | isteğe bağlı | Ekranda ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **ViewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyViewConfiguration` nesnesi sağlayın. Yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywallın görsel yapılandırmasını getirme](#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **EventListener** | isteğe bağlı | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı için `AdaptyUiDefaultEventListener`'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını işleme](android-handling-events) konusuna bakın. | | **PersonalizedOfferResolver** | isteğe bağlı | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver`'ı uygulayın ve `AdaptyPaywallProduct`'ı ürünün fiyatı kişiselleştirilmişse `true`, aksi hâlde `false` ile eşleştiren kendi mantığınızı geçirin. | | **TagResolver** | isteğe bağlı | Paywall metnindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve bunu karşılık gelen bir dizeyle eşleştirir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **ObserverModeHandler** | Observer mode için zorunlu | Önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | | **variationId** | zorunlu | Varyasyonun dize tanımlayıcısı. Bunu [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | | **transaction** | zorunlu |

iOS, StoreKit 1 için: bir [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.

iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.

Android için: Satın almanın billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneği olduğu satın almanın String tanımlayıcısı (`purchase.getOrderId()`).

|
Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın) 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu yapılandırın. 2. Adapty SDK'yı yükleyin ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlarımıza başvurun: [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) ve [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk). 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri bunlara atayın](create-paywall) ve Paywall Builder kullanarak özelleştirin. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını getirin](android-get-pb-paywalls).
1. `AdaptyUiObserverModeHandler` arayüzünü uygulayın. `AdaptyUiObserverModeHandler`'ın geri çağırımı (`onPurchaseInitiated`), kullanıcı bir satın alma işlemi başlattığında sizi bilgilendirir. Bu geri çağırıma yanıt olarak özel satın alma akışınızı şu şekilde tetikleyebilirsiniz: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Ayrıca, bu callback'leri AdaptyUI'ya iletmeyi unutmayın. Bu, yükleyiciyi göstermek gibi paywall'ın doğru çalışması için gereklidir: | Kotlin'de Callback | Java'da Callback | Açıklama | | :----------------- | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------- | | onStartPurchase() | onStartPurchase.invoke() | Bu callback, satın alma işleminin başladığını AdaptyUI'ya bildirmek için çağrılmalıdır. | | onFinishPurchase() | onFinishPurchase.invoke() | Bu callback, satın alma işleminin başarıyla tamamlandığını, tamamlanamadığını veya iptal edildiğini AdaptyUI'ya bildirmek için çağrılmalıdır. | 2. Görsel paywall'ı görüntüleyebilmek için önce başlatmanız gerekir. Bunun için `AdaptyUI.getPaywallView()` metodunu çağırın ya da `AdaptyPaywallView`'i doğrudan oluşturun: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler, ) //======= OR ======= val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { setEventListener(eventListener) setObserverModeHandler(observerModeHandler) showPaywall( viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver, tagResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler ); //======= OR ======= AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver); ``` ```xml showLineNumbers ``` Görünüm başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyip gösterebilirsiniz. İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Products** | opsiyonel | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` dizisi sağlayın. `null` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **ViewConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyViewConfiguration` nesnesi sağlayın. Yüklemek için `Adapty.getViewConfiguration(paywall)` metodunu kullanın. Daha fazla bilgi için [Paywall'ın görsel yapılandırmasını getirme](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) konusuna bakın. | | **Insets** | zorunlu | İçerik için dikey kenar boşlukları oluşturmak amacıyla sistem çubuklarının kapladığı alan hakkında bilgi içeren bir `AdaptyPaywallInsets` nesnesi tanımlayın. Ne durum çubuğu ne de gezinme çubuğu `AdaptyPaywallView`'ı kapatmıyorsa `AdaptyPaywallInsets.NONE` geçin. Sistem çubuklarının UI'ınızın bir kısmını kapladığı tam ekran modunda, insets'leri tablonun altında gösterildiği şekilde alın. | | **EventListener** | opsiyonel | Paywall olaylarını izlemek için bir `AdaptyUiEventListener` sağlayın. Kullanım kolaylığı açısından AdaptyUiDefaultEventListener'ı genişletmeniz önerilir. Daha fazla bilgi için [Paywall olaylarını yönetme](android-handling-events) konusuna bakın. | | **PersonalizedOfferResolver** | opsiyonel | Kişiselleştirilmiş fiyatlandırmayı ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) belirtmek için `AdaptyUiPersonalizedOfferResolver`'ı uygulayın ve `AdaptyPaywallProduct`'ı ürünün fiyatı kişiselleştirilmişse true, değilse false olarak eşleyen kendi mantığınızı geçirin. | | **TagResolver** | opsiyonel | Paywall metni içindeki özel etiketleri çözümlemek için `AdaptyUiTagResolver` kullanın. Bu çözümleyici bir etiket parametresi alır ve onu karşılık gelen bir dizeye dönüştürür. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **ObserverModeHandler** | Observer modu için zorunlu | Önceki adımda uyguladığınız `AdaptyUiObserverModeHandler`. | | **variationId** | zorunlu | Varyasyonun dize tanımlayıcısı. [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) nesnesinin `variationId` özelliğini kullanarak elde edebilirsiniz. | | **transaction** | zorunlu |

iOS, StoreKit1 için: bir [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.

iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.

Android için: Satın almanın billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneği olduğu satın almanın dize tanımlayıcısı (`purchase.getOrderId()`).

| Tam ekran modunda sistem çubuklarının kullanıcı arayüzünüzün bir bölümünü kapladığı durumlarda, inset'leri şu şekilde elde edin: ```kotlin showLineNumbers import androidx.core.graphics.Insets import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.of(insets.top, insets.bottom) paywallView.setEventListener(eventListener) paywallView.setObserverModeHandler(observerModeHandler) paywallView.showPaywall(viewConfig, products, paywallInsets, personalizedOfferResolver, tagResolver) } ``` ```java showLineNumbers import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, systemBarInsets.bottom); paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, paywallInsets, personalizedOfferResolver, tagResolver); return insets; }); ``` Returns: | Object | Description | | :------------------ | :------------------------------------------------- | | `AdaptyPaywallView` | İstenen paywall ekranını temsil eden nesne. | :::warning [Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode-android) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywall'dan geldiğini belirleyemez. :::
--- # File: android-troubleshoot-purchases --- --- title: "Android SDK'da satın alma sorunlarını giderme" description: "Android SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, Android SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrılıyor ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor, ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu durum genellikle Google Play Store kurulumunun eksik olduğuna ya da yapılandırma sorunlarına işaret eder. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## makePurchase iki kez çağrılıyor \{#makepurchase-is-invoked-twice\} **Sorun**: `makePurchase` metodu aynı satın alma için birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya hızlı kullanıcı etkileşimleri nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyelrorcantmakepayments-in-observer-mode\} **Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmanız ya da observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode-android) sayfasına bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan faturalandırma kullanılamıyor hatası alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın kullanılamadığını belirten bir Google Play Faturalandırma Kitaplığı hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store belgelerinden daha fazla bilgi edinebilirsiniz: [BillingResult yanıt kodlarını yönetme](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamıyor \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor ile ilgili sorunlarla karşılaşıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu işlem çoğu zaman sandbox ile ilgili satın alma tamamlama handler sorunlarını çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekirse [geçiş kılavuzlarını](android-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Yeni SDK sürümlerinde pek çok sorun giderilmiştir. --- # File: android-identifying-users --- --- title: "Android SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini geliştirmek için Adapty'de kullanıcıları tanımlayın (Android)." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamanız gerekir. Kullanıcıları Customer User ID'lerine göre [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz. ### Yapılandırma sırasında Customer User ID ayarlama \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçin: ```kotlin showLineNumbers Adapty.activate(applicationContext, "PUBLIC_SDK_KEY", customerUserId = "YOUR_USER_ID") ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Yapılandırma sonrasında Customer User ID ayarlama \{#setting-customer-user-id-after-configuration\} SDK yapılandırmasında kullanıcı ID'niz yoksa, daha sonra istediğiniz zaman `.identify()` metoduyla ayarlayabilirsiniz. Bu metodun en yaygın kullanım senaryoları; kayıt veya oturum açma sonrasında, kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçtiği anlardır. ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> if (error == null) { // successful identify } } ``` ```java showLineNumbers Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` İstek parametreleri: - **Customer User ID** (zorunlu): string türünde kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Bir kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahiptir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmaya otomatik olarak geçecektir. Anonim kullanıcıya özel özellikler veya üçüncü taraf ağlardan attribution gibi herhangi bir veri iletildiyse, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden istemeniz gerektiğini unutmayın. ::: ### Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\} İstediğiniz zaman `.logout()` metodunu çağırarak kullanıcının oturumunu kapatabilirsiniz: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` Ardından `.identify()` metodunu kullanarak kullanıcı girişi yapabilirsiniz. ### Cihazlar Arası Kullanıcı Tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: android-setting-user-attributes --- --- title: "Android SDK'da kullanıcı özelliklerini ayarlama" description: "Daha iyi kitle segmentasyonu için Adapty'de kullanıcı özelliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulama kullanıcılarınıza e-posta, telefon numarası gibi isteğe bağlı özellikler ekleyebilirsiniz. Bu özellikleri kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz. ### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } ``` ```java showLineNumbers AdaptyProfileParameters.Builder builder = new AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(new AdaptyProfile.Date(1970, 1, 3)); Adapty.updateProfile(builder.build(), error -> { if (error != null) { // handle the error } }); ``` `updateProfile` metoduyla daha önce ayarladığınız özellikler sıfırlanmaz. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen `` anahtarları ve `` değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| |

email

phoneNumber

firstName

lastName

| String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı özellikleri \{#custom-user-attributes\} Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin fitness uygulamaları için haftalık egzersiz sayısı, dil öğrenme uygulamaları için kullanıcının bilgi düzeyi gibi. Bu özellikleri, hedefli paywall'lar ve teklifler oluşturmak için segmentlerde kullanabilir; ayrıca hangi ürün metriklerinin geliri en çok etkilediğini anlamak için analitikte de değerlendirebilirsiniz. ```kotlin showLineNumbers builder.withCustomAttribute("key1", "value1") ``` ```java showLineNumbers builder.withCustomAttribute("key1", "value1"); ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```kotlin showLineNumbers builder.withRemovedCustomAttribute("key2") ``` ```java showLineNumbers builder.withRemovedCustomAttribute("key2"); ``` Bazen önceden hangi özel özelliklerin ayarlandığını öğremeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı özellikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, son senkronizasyondan bu yana sunucudaki özellikler değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel özellik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ile şu karakterleri içerebilir: `_` `-` `.` - Değer, en fazla 50 karakter uzunluğunda string veya float olabilir. --- # File: android-listen-subscription-changes --- --- title: "Android SDK'da abonelik durumunu kontrol etme" description: "Android uygulamanızda müşteri elde tutmayı iyileştirmek için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek çok kolaydır. Ürün kimliklerini kodunuza manuel olarak eklemenize gerek yoktur. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. Abonelik durumunu kontrol etmeye başlamadan önce [Gerçek Zamanlı Geliştirici Bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) kurulumunu yapın. ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesinin özellikleridir. Profili uygulamanız başladığında, örneğin [bir kullanıcı tanımladığınızda](android-identifying-users#setting-customer-user-id-on-configuration) alıp değişiklikler gerçekleştiğinde güncellemenizi öneririz. Bu sayede profil nesnesini tekrar tekrar istek göndermeden kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Profil güncellemelerini dinleme, access level dahil](android-listen-subscription-changes) bölümünde açıklandığı gibi profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Sunucudan access level alma \{#retrieving-the-access-level-from-the-server\} Sunucudan access level almak için `.getProfile()` metodunu kullanın: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- | ------------------------------------------------------------ | | Profile |

Bir [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) nesnesi. Genel olarak, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.

`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu sağlar. Herhangi bir nedenle (örneğin internet bağlantısı olmadığında) Adapty SDK sunucudan bilgi alamazsa, önbellekteki veriler döndürülür. Adapty SDK'nın bilgileri mümkün olduğunca güncel tutmak için `AdaptyProfile` önbelleğini düzenli olarak güncellediğini de belirtmek gerekir.

| `.getProfile()` metodu, kullanıcı profilini size sağlar ve bu profilden access level durumunu öğrenebilirsiniz. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız "sports" ve "science" gibi access level'lar oluşturabilirsiniz. Ancak çoğu durumda yalnızca bir access level'a ihtiyaç duyarsınız; bu durumda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmeye yönelik bir örnek: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("premium"); if (premium != null && premium.isActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` ```java showLineNumbers t Adapty.setOnProfileUpdatedListener(profile -> { // handle any changes to subscription state }); ``` Adapty, uygulamanın başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'da uygulanan önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu kullanılamaz olsa bile, profil abonelik durumuna ilişkin bilgilere önbellekteki verilerden erişilebilir. Ancak önbellekten doğrudan veri talep etmenin mümkün olmadığını belirtmek gerekir. SDK, profille ilgili güncellemeleri ve değişiklikleri kontrol etmek için sunucuyu periyodik olarak her dakika sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler olduğunda, bunlar önbellekteki veriyle sunucuyla senkronize kalması için önbelleğe gönderilir. --- # File: kids-mode-android --- --- title: "Android SDK'da Kids Mode" description: "Google politikalarına uymak için Kids Mode'u kolayca etkinleştirin. Android SDK'da GAID veya reklam verisi toplanmaz." --- Android uygulamanız çocuklara yönelikse [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikalara uygun şekilde yapılandırabilir ve uygulama mağazası incelemelerini geçebilirsiniz. ## Ne yapılması gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunlara ek olarak, customer user ID kullanımında dikkatli olmanızı öneririz. `` formatındaki kullanıcı kimlikleri, e-posta kullanımında olduğu gibi kişisel veri toplama olarak değerlendirilecektir. Kids Mode için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (ör. karma kimlikler veya cihaz tarafından üretilen UUID'ler) kullanmaktır. ## Kids Mode'u Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'ndeki güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzdaki güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için Adapty SDK'yı başlatırken Android Advertising ID (AAID/GAID) ve IP adresi toplamasını devre dışı bırakmanız gerekir: **Kotlin:** ```kotlin showLineNumbers override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ) } ``` **Java:** ```java showLineNumbers @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ); } ``` ### Android manifest'inizdeki güncellemeler \{#updates-in-your-android-manifest\} :::note Uygulamanız **yalnızca** çocuklara yönelikse ve Android 13 (API 33) veya daha yüksek bir sürümü hedefliyorsa, Google Play `AD_ID` iznini talep etmemenizi zorunlu kılar. Uygulamanızdaki başka bir SDK (analitik, attribution veya reklam), manifest birleştirme yoluyla bu izni ekleyebilir. `withAdIdCollectionDisabled(true)` ayarını yapmak, Adapty'nin kimliği toplamasını engeller; ancak başka bir SDK tarafından tanımlanan bir izni kaldırmaz. ::: İzni kaldırmak için aşağıdaki kodu `app/src/main/AndroidManifest.xml` dosyasındaki `` öğesinin içine ekleyin. `` öğesinin `xmlns:tools="http://schemas.android.com/tools"` bildirimini içermesi gerekir. ```xml showLineNumbers title="AndroidManifest.xml" ``` --- # File: android-get-onboardings --- --- title: "Android SDK'da onboarding'leri al" description: "Adapty'de Android için onboarding'leri nasıl alacağınızı öğrenin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları edinme](android-get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](android-present-paywalls) sayfalarına bakın. ::: Adapty Kontrol Paneli'nde builder ile [onboarding'in görsel kısmını tasarladıktan](design-onboarding) sonra, onu Android uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, onboarding'i placement ile ilişkilendirmek ve aşağıda açıklanan görünüm yapılandırmasını almaktır. Başlamadan önce şunları sağlayın: 1. [Adapty Android SDK](sdk-installation-android) sürüm 3.8.0 veya daha yüksek sürümü yüklemiş olun. 2. [Bir onboarding oluşturmuş](create-onboarding) olun. 3. Onboarding'i bir [placement](placements)'a eklemiş olun. ## Onboarding'i çekme \{#fetch-onboarding\} Kodsuz builder'ımızla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın çekip göstermesi gereken bir yapılandırma içeren container olarak saklanır. Bu container tüm deneyimi yönetir — hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (quiz yanıtları veya form girişleri gibi) nasıl işleneceğini belirler. Container ayrıca analitik olaylarını otomatik olarak takip eder, dolayısıyla ayrıca görüntüleme takibi eklemeniz gerekmez. En iyi performans için, kullanıcılara göstermeden önce görsellerin yüklenmesine yeterli zaman tanımak amacıyla onboarding yapılandırmasını erken aşamada çekin. Onboarding almak için `getOnboarding` metodunu kullanın: ```kotlin showLineNumbers Adapty.getOnboarding("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // the requested onboarding } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa bunu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ama internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı çekmek için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı sağlamak için tasarlanmıştır.

| | **loadTimeout** | varsayılan: 5 sn |

Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.

Nadiren bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.

Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`, burada `.seconds` `import com.adapty.utils.seconds`'dan gelir) ya da `TimeInterval.seconds(5)` kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.

| Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyOnboarding`](https://android.adapty.io/adapty/com.adapty.models/-adapty-onboarding/) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding çekmeyi hızlandırma \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Onboarding'ler genellikle neredeyse anında çekilir, dolayısıyla bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz olduğunda ve kullanıcılarınızın internet bağlantısı zayıf olduğunda, onboarding'i çekmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için onboarding'i çeken `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Çekme](#fetch-onboarding) bölümünde açıklandığı gibi `getOnboarding` metodu ile onboarding çekmek olduğunu unutmamak önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı değerlendirin; çünkü ikincisinin önemli kısıtlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorun yaratabilir; geriye dönük uyumlu tasarımlar yapmanızı ya da eski sürümlerin yanlış görüntüleneceğini kabul etmenizi gerektirebilir. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı çekme bu dezavantajlardan ağır basıyorsa aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```kotlin Adapty.getOnboardingForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // Handle successful onboarding retrieval } is AdaptyResult.Error -> { val error = result.error // Handle error case } } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** |

isteğe bağlı

varsayılan: `en`

|

Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi bölge içindir.

Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.

Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.

| | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |

SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.

Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa bunu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ama internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.

Önbelleğin uygulama yeniden başlatıldığında bozulmadığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.

Adapty SDK onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı çekmek için CDN, CDN'e erişilemeyen durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı sağlamak için tasarlanmıştır.

| --- # File: android-present-onboardings --- --- title: "Android SDK'da onboarding'leri göster" description: "Etkili kullanıcı etkileşimi için Android'de onboarding'leri nasıl sunacağınızı öğrenin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı olmadan kullanım elde edersiniz. Başlamak için [Flow'ları ve paywall'ları al](android-get-pb-paywalls) ve [Flow'ları ve paywall'ları göster](android-present-paywalls) sayfalarına göz atın. ::: Başlamadan önce şunlardan emin olun: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 veya daha yeni bir sürümünü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Onboarding Builder ile bir onboarding özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render işlemiyle uğraşmanıza gerek yok. Bu tür bir onboarding, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. Cihaz ekranında görsel onboarding'i gösterebilmek için önce yapılandırmanız gerekir. Bunu yapmak için `AdaptyUI.getOnboardingView()` metodunu çağırın veya `OnboardingView`'ı doğrudan oluşturun: ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener); ``` ```xml ``` View başarıyla oluşturulduktan sonra, onu görünüm hiyerarşisine ekleyebilir ve cihaz ekranında görüntüleyebilirsiniz. İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :-------- | :------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfig** | zorunlu | `AdaptyUI.getOnboardingConfiguration()` ile elde edilen onboarding yapılandırması | | **eventListener** | zorunlu | Onboarding olaylarını işlemek için `AdaptyOnboardingEventListener` uygulaması. Ayrıntılar için [Onboarding olaylarını işleme](android-handle-onboarding-events) bölümüne bakın. | ## Yükleme göstergesi rengini değiştirme \{#change-loading-indicator-color\} Yükleme göstergesinin varsayılan rengini şu şekilde geçersiz kılabilirsiniz: ```xml ``` ## Splash ekranı ile onboarding arasına sorunsuz geçiş ekleme \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\} Varsayılan olarak, splash ekranı ile onboarding arasında onboarding tam olarak yüklenene kadar yükleme ekranı görünür. Ancak geçişi daha akıcı hale getirmek istiyorsanız bunu özelleştirebilir; splash ekranını uzatabilir ya da başka bir şey gösterebilirsiniz. Bunu yapmak için `res/layout` dizininde `adapty_onboarding_placeholder_view.xml` dosyası oluşturun ve onboarding yüklenirken gösterilecek yer tutucuyu orada tanımlayın. Bir yer tutucu tanımladığınızda onboarding arka planda yüklenir ve hazır olduğunda otomatik olarak görüntülenir. ## Güvenli alan dolgularını devre dışı bırakma \{#disable-safe-area-paddings\} Varsayılan olarak, onboarding view durum çubuğu ve gezinme çubuğu gibi sistem arayüzü öğelerini önlemek amacıyla güvenli alan dolgularını otomatik olarak uygular. Ancak bu davranışı devre dışı bırakarak layout üzerinde tam kontrol sahibi olmak istiyorsanız `safeAreaPaddings` parametresini `false` olarak ayarlayabilirsiniz. ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener, safeAreaPaddings = false ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener, safeAreaPaddings = false ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener, false ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener, false); ``` Alternatif olarak, uygulamanıza bir boolean kaynağı ekleyerek bu davranışı genel düzeyde kontrol edebilirsiniz: ```xml false ``` `safeAreaPaddings` değeri `false` olarak ayarlandığında, onboarding otomatik dolgu ayarlaması yapılmadan tam ekrana uzanır; bu sayede layout üzerinde tam kontrol sağlanır ve onboarding içeriği ekranın tamamını kullanabilir. ## Onboardinglerde linklerin nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboardinglerde linklerin nasıl açılacağını özelleştirme, Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboardinglerdeki linkler uygulama içi bir tarayıcıda açılır. Bu, web sayfalarını uygulamanızın içinde göstererek kullanıcıların uygulamalar arasında geçiş yapmadan görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sunar. Linklerin bunun yerine harici bir tarayıcıda açılmasını tercih ederseniz, `externalUrlsPresentation` parametresini `AdaptyWebPresentation.ExternalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```kotlin val onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ) ``` ```java AdaptyOnboardingConfiguration onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding, AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ); ``` --- # File: android-handle-onboarding-events --- --- title: "Android SDK'da onboarding olaylarını yönetme" description: "Adapty kullanarak Android'de onboarding ile ilgili olayları yönetin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda native olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü ve hissi, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywallları al](android-get-pb-paywalls) ve [Flow'ları ve paywallları göster](android-present-paywalls) bölümlerine bakın. ::: Başlamadan önce şunları sağlayın: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 veya daha yeni bir sürümünü yüklediniz. 2. Bir [onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin. Android uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyOnboardingEventListener` arayüzünü uygulayın. ## Özel eylemler \{#custom-actions\} Builder'da bir düğmeye **custom** (özel) eylem ekleyebilir ve buna bir ID atayabilirsiniz. Ardından bu ID'yi kodunuzda kullanarak özel eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir düğmeye dokunduğunda, `onCustomAction` delegate metodu builder'daki eylem ID'siyle tetiklenir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```kotlin showLineNumbers class YourActivity : AppCompatActivity() { private val eventListener = object : AdaptyOnboardingEventListener { override fun onCustomAction(action: AdaptyOnboardingCustomAction, context: Context) { when (action.actionId) { "allowNotifications" -> { // Request notification permissions } } } override fun onError(error: AdaptyOnboardingError, context: Context) { // Handle errors } // ... other required delegate methods } } ```
Olay örneği (Genişletmek için tıklayın) ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
## Onboarding'i kapatma \{#closing-onboarding\} Kullanıcı **Close** eylemi atanmış bir düğmeye dokunduğunda onboarding kapatılmış sayılır. Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerekir. Örneğin: :::important Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerekir. Örneğin onboarding'in kendisini ekrandan kaldırmanız gerekir. ::: Örneğin: ```kotlin override fun onCloseAction(action: AdaptyOnboardingCloseAction, context: Context) { // Dismiss the onboarding screen (context as? Activity)?.onBackPressed() } ```
Olay örneği (Genişletmek için tıklayın) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
## Paywall açma \{#opening-a-paywall\} :::tip Eğer paywall'ı onboarding içinde açmak istiyorsanız bu olayı ele alın. Paywall kapandıktan sonra açmak istiyorsanız daha doğrudan bir yöntem var: [`AdaptyOnboardingCloseAction`](#closing-onboarding) olayını ele alın ve olay verisine gerek kalmadan paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, action ID'yi bir paywall placement ID'siyle eşit tutmaktır. Bu şekilde `AdaptyOnboardingOpenPaywallAction` sonrasında placement ID'yi kullanarak paywall'ı hemen alıp açabilirsiniz: ```kotlin override fun onOpenPaywallAction(action: AdaptyOnboardingOpenPaywallAction, context: Context) { // Get the paywall using the placement ID from the action Adapty.getPaywall(placementId = action.actionId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Get the paywall configuration AdaptyUI.getViewConfiguration(paywall) { result -> when(result) { is AdaptyResult.Success -> { val paywallConfig = result.value // Create and present the paywall val paywallView = AdaptyUI.getPaywallView( activity = this, viewConfig = paywallConfig, products, eventListener = paywallEventListener ) // Add the paywall view to your layout binding.container.addView(paywallView) } is AdaptyResult.Error -> { val error = result.error // handle the error } } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } } ```
Olay örneği (Genişletmek için tıklayın) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
## Onboarding yüklemesinin tamamlanması \{#finishing-loading-onboarding\} Onboarding yüklenmeyi tamamladığında bu metod çağrılır: ```kotlin override fun onFinishLoading(action: AdaptyOnboardingLoadedAction, context: Context) { // Handle loading completion } ```
Olay örneği (Genişletmek için tıklayın) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
## Navigasyon olayları \{#navigation-events\} `onAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır. `event` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `OnboardingStarted` | Onboarding yüklendiğinde | | `ScreenPresented` | Herhangi bir ekran gösterildiğinde | | `ScreenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcının yanıtı) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `SecondScreenPresented` | İkinci ekran gösterildiğinde | | `UserEmailCollected` | Kullanıcının e-posta adresi giriş alanı aracılığıyla toplandığında tetiklenir | | `OnboardingCompleted` | Kullanıcı `final` ID'li bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyaç duyuyorsanız son ekrana `final` ID'sini atayın. | | `Unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veri) içerir | Her olay şu alanları içeren `meta` bilgisi barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Geçerli ekranın tanımlayıcısı | | `screenIndex` | Akıştaki geçerli ekranın konumu | | `totalScreens` | Akıştaki toplam ekran sayısı | Analitik olayları takip etmek için nasıl kullanabileceğinize dair bir örnek: ```kotlin override fun onAnalyticsEvent(event: AdaptyOnboardingAnalyticsEvent, context: Context) { when (event) { is AdaptyOnboardingAnalyticsEvent.OnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingAnalyticsEvent.OnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingAnalyticsEvent.Unknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } ```
Olay örnekleri (Genişletmek için tıklayın) ```javascript // OnboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // ScreenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // ScreenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // SecondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // UserEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // OnboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
--- # File: android-onboarding-input --- --- title: "Android SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Android uygulamanızda onboarding verilerini kaydedin ve kullanın." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](android-get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir Android görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları alma](android-get-pb-paywalls) ile [Flow'ları ve paywall'ları gösterme](android-present-paywalls) sayfalarına göz atın. ::: Kullanıcılarınız bir test sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```kotlin override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle single selection } is AdaptyOnboardingStateUpdatedParams.MultiSelect -> { // Handle multiple selections } is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input } is AdaptyOnboardingStateUpdatedParams.DatePicker -> { // Handle date selection } } } ``` Aksiyon formatını [buradan](https://android.adapty.io/adapty-ui/com.adapty.ui.onboardings.actions/-adapty-onboarding-state-updated-action/) inceleyebilirsiniz.
Kaydedilen veri örnekleri (format, implementasyonunuza göre farklılık gösterebilir) ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ```
## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken girilen verileri kullanarak [kullanıcı profilini güncellemeniz](android-setting-user-attributes) gerekir. Örneğin, kullanıcılardan `name` ID'sine sahip metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak ayarlamak istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmelerini de istiyorsunuz. Uygulama kodunuzda bu şu şekilde görünebilir: ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (action.elementId) { "name" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Text -> { builder.withFirstName(inputParams.value) } } } "email" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Email -> { builder.withEmail(inputParams.value) } } } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboardinglardaki quizleri kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara sporla deneyimleri hakkında soru sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding builder'a bir [quiz ekleyin](onboarding-quizzes) ve seçeneklerine anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler belirleyin](android-setting-user-attributes). ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Handle quiz responses and set custom attributes when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (action.elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.params.value) } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` 3. Her özel nitelik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda ilgili placement için [bir paywall gösterin](android-paywalls). Onboardinginizde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](android-handle-onboarding-events#opening-a-paywall) olarak uygulayın. --- # File: android-sdk-call-order --- --- title: "Android SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak kayıp premium erişim, eksik attribution ve aralıklı ADAPTY_NOT_INITIALIZED hatalarından kaçının." --- `Adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağırmamalısınız. Bu tamamlanana kadar SDK'nın hiçbir durumu yoktur. `activate()` öncesinde veya bununla eş zamanlı yapılan her çağrı [`ADAPTY_NOT_INITIALIZED`](android-sdk-error-handling) hatasıyla başarısız olur. Uygulamanız kullanıcıların kimliğini doğruluyorsa ve başlatma sonrasında bir customer user ID topluyorsanız, bu noktada `Adapty.identify()` çağrısı yapın. `identify` tamamlanma callback'i tetiklenene kadar kullanıcı eylemi yöntemlerini çağırmayın. Bununla yarışan çağrılar ya callback'lerinde hata döndürür ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu olduğunda attribution, `appsflyer_id` gibi MMP ID'leri ve kurulum sahipliği tanımlanan profile her zaman aktarılmaz. Uygulamanız kullanıcıların kimliğini doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. Bunları önce başlatın ve `Adapty.activate` çağrısı yapmadan önce UID geri çağrılarını bekleyin. Aksi takdirde MMP ID'si kısa süreli anonim bir profile düşer ve her zaman tanımlanmış profile aktarılmaz. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıralama \{#the-correct-order\} İzleyeceğiniz yol iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK yöntemlerini çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama başlangıcında müşteri kullanıcı kimliğine sahipseniz, `activate()` çağrısından önce bunu `AdaptyConfig.Builder`'a aktarın (2a. adım). Bu yol hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gerekli değildir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlangıcında, ilk olarak | MMP'nin UID geri çağrısını bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `Adapty.activate(context, AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | Uygulama başlangıcında, adım 1'den sonra, müşteri kullanıcı kimliğiniz varsa | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `Adapty.activate(context, AdaptyConfig.Builder("KEY").build())` `customerUserId` olmadan | Uygulama başlangıcında, adım 1'den sonra, müşteri kullanıcı kimliğiniz yoksa (veya hiç toplanmıyorsa) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` | Adım 2'den sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP kimliklerinin doğru profile atanması için gereklidir. | | 4 | `Adapty.identify("YOUR_USER_ID") { error -> ... }` | Adım 3'ten sonra (veya MMP yoksa adım 2'den sonra), adım 5'ten önce — yalnızca kimlik doğrulama ile 2b yolunda | Tamamlama geri çağrısını kullanın. `identify` sırasında eş zamanlı çağrılar anonim profile düşebilir. | | 5 | `getPaywall`, `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız adım 4'ten sonra; aksi hâlde adım 3'ten sonra (veya MMP yoksa adım 2'den sonra) | Bu çağrılar kararlı bir profile ihtiyaç duyar. | :::important Bu adımları atlamak, geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitleye karşı döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar web ödeme sayfasında (Stripe, Paddle) satın alım yapıp ardından uygulamayı yüklerse, cihazdaki ilk `activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Kimlik doğrulama akışınızdan veya install referrer'dan uygulama başlamadan önce kullanıcı ID'sini çözümleyebiliyorsanız, doğrudan `AdaptyConfig.Builder` içinde belirtin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` ve ardından `restorePurchases` çağrısı yapılana kadar cihazda görünmez. Her web ödeme sayfasıyla göndereceğiniz metadata için şu sayfalara bakın: - [Stripe](stripe) - [Paddle](paddle) --- # File: android-optimize-paywall-fetching --- --- title: "Android SDK'da paywall çekmeyi optimize etme" description: "Adapty paywalllarını güvenilir şekilde çekin: Android için zamanlama, önbellekleme ve yedek kalıplar." --- Android'de güvenilir bir paywall çekme işlemi üç şeyi yapar: hızlı render eder, kitleye hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz biçimde yedek gösterir. Aşağıdaki kurallar bu hedefe ulaşmak için gereken zamanlama, önbellekleme ve yedek kalıpları kapsar. :::tip Bu kurallar, `Adapty.activate()` ve `Adapty.identify()` işlevlerinin zaten tamamlandığını varsayar. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). ::: ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Bunu yapın | Bunu yapmayın | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı getirin. | Başlatma sırasında tüm placement'ları eş zamanlı olarak önceden getirin. | Toplu ön getirme ana thread'i bloke eder ve bu sürede siyah ekran görünür. | | `getPaywall`'ı attribution çözümlenme şansı bulduktan sonra çağırın — örneğin `activate`'ten 1-2 saniye sonra veya `setOnProfileUpdatedListener` tetiklendikten sonra. | `getPaywall`'ı `Application.onCreate()` içinde çağırın. | Attribution henüz gelmemiştir. Paywall varsayılan kitleye göre çözümlenir ve segment ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` ayarlayın ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ı süresiz olarak bekleyin. | Zaman aşımı olmadan, zayıf bağlantıdaki kullanıcılar ağ çözümlenene kadar boş ekran görür ya da uygulamayı kapatır. | `fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products-android) sayfasına, doğru placement seçimi için ise [Placement'lar](placements) sayfasına bakın. ## Zayıf bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantı yaşanan pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunlarından etkilenen bölgeler): - İlk fetch dışındaki her fetch işleminde `fetchPolicy` değerini `AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad` olarak ayarlayın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalla geçin. - Paywall gösterimini `getProfile`'a bağlamayın. `getPaywall` fonksiyonunu bağımsız olarak çağırın; böylece yavaş bir profil yüklenmesi arayüzü bloke etmez. --- # File: android-test --- --- title: "Android SDK'da test ve yayınlama" description: "Adapty ile Android uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Adapty SDK'yı Android uygulamanıza zaten entegre ettiyseniz, her şeyin doğru şekilde kurulduğunu ve satın almaların beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de Google Play'in sandbox ortamıyla gerçek satın alma akışını test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Sandbox testi ve kapalı iz doğrulaması dahil olmak üzere uygulama içi satın almalarınızı kapsamlı biçimde test etmek için [test rehberimize](testing-on-android) bakın. ## Yayın öncesi hazırlık \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesini](release-checklist) takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'ye raporlanıyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanmış --- # File: android-sdk-error-handling --- --- title: "Android SDK'da hataları yönetin" description: "Adapty'nin sorun giderme rehberiyle Android SDK hatalarını etkili bir şekilde yönetin." --- SDK tarafından döndürülen her hata `AdaptyError` türündedir. :::tip **Hata ayıklamadan önce ayrıntılı logları etkinleştirin.** Çoğu `AdaptyError`, temel bir Play Billing, ağ veya backend hatasını sarmalıyor. Ayrıntılı loglar açıkken (`Adapty.logLevel = AdaptyLogLevel.VERBOSE` — bkz. [Loglama](sdk-installation-android#logging)), sarmalanan hata konsola yazdırılır ve genellikle asıl nedeni ortaya koyar. ::: :::important Bu çözümler sorununuzu gidermezse, destek ekibiyle iletişime geçmeden önce atmanız gereken adımlar için [Diğer sorunlar](#other-issues) bölümüne bakın; bu sayede size daha verimli yardım edebiliriz. ::: | Hata | Çözüm | |----------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | UNKNOWN | Bu hata, bilinmeyen veya beklenmedik bir hata oluştuğunu gösterir. | | [ITEM_UNAVAILABLE](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_UNAVAILABLE()) | Bu hata çoğunlukla test aşamasında ortaya çıkar. Ürünlerin production'da bulunmadığı ya da kullanıcının Google Play'deki Testers grubuna dahil olmadığı anlamına gelebilir. | | ADAPTY_NOT_INITIALIZED | Adapty SDK etkinleştirilmemiş.
En sık, splash screen veya erken çalışan bir UI bileşeninin `Adapty.activate` tamamlanmadan önce Adapty metodlarını çağırmasından kaynaklanır. Gerçek cihaz zamanlaması emülatörden farklı olduğu için bu sorun aralıklı olarak ortaya çıkabilir ve emülatörde yeniden üretilmeyebilir. Başka SDK çağrılarını planlamadan önce `Adapty.activate` tamamlanmasını bekleyin. Tam sıra için [Android SDK'da çağrı sırası](android-sdk-call-order) konusuna bakın. Ayrıca `Adapty.activate` metoduyla [Adapty SDK'yı doğru şekilde yapılandırmanız](sdk-installation-android#activate-adapty-module-of-adapty-sdk) gerekir. | | PROFILE_WAS_CHANGED | İşlem sırasında kullanıcı profili değiştirildi.
Bu durum, `Adapty.identify` hâlâ devam ederken başka bir metod çağrıldığında yaşanır; devam eden çağrı değiştirilmek üzere olan bir profile denk gelir ve SDK onu reddeder. Diğer SDK çağrılarını planlamadan önce `Adapty.identify` tamamlanmasını bekleyin. Bkz. [Android SDK'da çağrı sırası](android-sdk-call-order). | | PRODUCT_NOT_FOUND | Bu hata, satın alınmak istenen ürünün mağazada mevcut olmadığını gösterir. | | INVALID_JSON |

Yerel yedek paywall JSON'ı geçerli değil.

Önce varsayılan İngilizce paywallınızı düzeltin, ardından geçersiz yerel paywallları değiştirin. Bir paywallın nasıl düzeltileceğine dair ayrıntılar için [Paywall'ı remote config ile özelleştirme](customize-paywall-with-remote-config) konusuna, yerel paywallların nasıl değiştirileceğine dair ayrıntılar için ise [Yerel yedek paywallları tanımlama](fallback-paywalls) konusuna bakın.

| |

CURRENT_SUBSCRIPTION_TO_UPDATE

\_NOT_FOUND_IN_HISTORY

| Değiştirilmesi gereken orijinal abonelik, aktif abonelikler arasında bulunamadı. | | [BILLING_SERVICE_TIMEOUT](https://developer.android.com/google/play/billing/errors#service_timeout_error_code_-3) | Bu hata, Google Play yanıt veremeden isteğin maksimum zaman aşımına ulaştığını gösterir. Örneğin, Play Billing Library çağrısının talep ettiği işlemin gecikmesinden kaynaklanabilir. | | [FEATURE_NOT_SUPPORTED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#FEATURE_NOT_SUPPORTED()) | İstenen özellik, mevcut cihazda Play Store tarafından desteklenmiyor. | | [BILLING_SERVICE_DISCONNECTED](https://developer.android.com/google/play/billing/errors#service_disconnected_error_code_-1) | Bu hata, istemci uygulamanın `BillingClient` aracılığıyla Google Play Store hizmetiyle kurduğu bağlantının kesildiğini gösterir. | | [BILLING_SERVICE_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#service_unavailable_error_code_2) | Bu hata, Google Play Billing hizmetinin şu anda kullanılamaz durumda olduğunu gösterir. Çoğu durumda bu, istemci cihaz ile Google Play Billing hizmetleri arasındaki bir noktada ağ bağlantısı sorunu olduğu anlamına gelir. | | [BILLING_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) |

Bu hata, satın alma işlemi sırasında bir faturalandırma sorunu oluştuğunu gösterir. Olası nedenler şunlardır:

1. Kullanıcının cihazındaki Play Store uygulaması eksik veya güncel değil.

2. Kullanıcı desteklenmeyen bir ülkede.

3. Kullanıcı, yöneticinin satın almaları devre dışı bıraktığı bir kurumsal hesabın parçası.

4. Google Play, kullanıcının ödeme yöntemini tahsil edemedi (örneğin süresi dolmuş bir kredi kartı).

5. Kullanıcı Play Store uygulamasında oturum açmamış.

| | [DEVELOPER_ERROR](https://developer.android.com/google/play/billing/errors#developer_error) | Bu hata, bir API'nin hatalı kullanıldığını gösterir. | | [BILLING_ERROR](https://developer.android.com/google/play/billing/errors#error_error_code_6) | Bu hata, Google Play'in kendi içinde bir sorun olduğunu gösterir. | | [ITEM_ALREADY_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_ALREADY_OWNED()) | Ürün zaten satın alınmış. | | [ITEM_NOT_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_NOT_OWNED()) | Bu hata, kullanıcının ürüne sahip olmadığı için istenen işlemin gerçekleştirilemediğini gösterir. | | [BILLING_NETWORK_ERROR](https://developer.android.com/google/play/billing/errors#network_error_error_code_12) | Bu hata, cihaz ile Play sistemleri arasındaki ağ bağlantısında bir sorun olduğunu gösterir. | | NO_PRODUCT_IDS_FOUND |

Bu hata, paywallda yer alan ürünlerin hiçbirinin mağazada mevcut olmadığını gösterir.

Bu hatayla karşılaşıyorsanız sorunu çözmek için aşağıdaki adımları izleyin:

  1. Tüm ürünlerin Adapty Kontrol Paneli'ne eklenip eklenmediğini kontrol edin.
  2. Uygulamanızın **Package name** değerinin Google Play Console'daki ile eşleştiğinden emin olun.
  3. Uygulama mağazalarındaki ürün tanımlayıcılarının Kontrol Paneli'ne eklediğiniz tanımlayıcılarla örtüştüğünü doğrulayın. Tanımlayıcıların Bundle ID içermemesi gerektiğini unutmayın; Bundle ID zaten mağazada dahilse bu kural uygulanmaz.
  4. Google vergi ayarlarınızda uygulamanın ödeme durumunun **Active** olduğunu onaylayın. Vergi bilgilerinizin güncel ve sertifikalarınızın geçerli olduğundan emin olun.
  5. Uygulamaya bir banka hesabının bağlı olup olmadığını kontrol edin; bu, uygulamanın para kazanmaya uygun olması için gereklidir.
  6. Ürünlerin bulunduğunuz bölgede kullanılabilir olup olmadığını kontrol edin.
  7. Uygulamanızın test kanallarından birinde olduğundan emin olun. **Internal testing** kanalı inceleme gerektirmediği ve uygulamayı müşterilerden gizli tuttuğu için en kolay seçenektir.
| | NO_PURCHASES_TO_RESTORE | Bu hata, Google Play'in geri yüklenecek satın alma işlemi bulamadığını gösterir. | | AUTHENTICATION_ERROR | `Adapty.activate` metoduyla [Adapty SDK'yı doğru şekilde yapılandırmanız](sdk-installation-android#activate-adapty-module-of-adapty-sdk) gerekiyor. | | BAD_REQUEST | Hatalı istek.
[Google Play ile entegrasyon](google-play-store-connection-configuration) için gerekli tüm adımları tamamladığınızdan emin olun. | | SERVER_ERROR | Sunucu hatası. | | REQUEST_FAILED | Bu hata, düzgün tanımlanamayan bir ağ sorununu gösterir. | | DECODING_FAILED | Yanıt çözümlenemedi.
Kodunuzu gözden geçirin ve gönderdiğiniz parametrelerin geçerli olduğundan emin olun. Örneğin bu hata, geçersiz bir API anahtarı kullandığınıza işaret edebilir. | | ANALYTICS_DISABLED | [Devre dışı bıraktığınız](analytics-integration#disabling-external-analytics-for-a-specific-customer) için analytics etkinliklerini işleyemiyoruz. | | WRONG_PARAMETER | Bu hata, bazı parametrelerinizin hatalı olduğunu gösterir: boş olamayacak bir alan boş bırakılmış ya da yanlış tür kullanılmış vb. | ## Diğer sorunlar \{#other-issues\} Henüz bir çözüm bulamadıysanız, sonraki adımlar şunlar olabilir: - **SDK'yı en son sürüme yükseltme**: En son SDK sürümleri daha kararlıdır ve bilinen sorunlara yönelik düzeltmeler içerir; bu nedenle her zaman güncellemenizi öneririz. - **Destek ekibiyle iletişime geçin veya diğer geliştiricilerden yardım alın** [destek forumunda](https://adapty.featurebase.app/). - **Destek ekibiyle [support@adapty.io](mailto:support@adapty.io) adresinden veya sohbet üzerinden iletişime geçin**: SDK'yı yükseltmeye hazır değilseniz ya da yükseltme sorunu çözmediyse destek ekibimize ulaşın. [Ayrıntılı günlük kaydını etkinleştirip](sdk-installation-android#logging) günlükleri ekiple paylaşırsanız sorununuz daha hızlı çözülür. İlgili kod parçacıklarını da ekleyebilirsiniz. --- # File: migration-to-android-sdk-v4 --- --- title: "Adapty Android SDK'yı v. 4.0'a Geçirme" description: "Adapty Android SDK v4.0'a geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty Android SDK 4.0, flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır; Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı referans \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty.getPaywall(placementId, locale)` | `Adapty.getFlow(placementId)` | | `Adapty.getPaywallForDefaultAudience(placementId, locale)` | `Adapty.getFlowForDefaultAudience(placementId)` | | `AdaptyUI.getViewConfiguration(paywall)` | `AdaptyUI.getFlowConfiguration(flow, locale)` | | `AdaptyUI.LocalizedViewConfiguration` | `AdaptyUI.FlowConfiguration` | | `Adapty.getPaywallProducts(paywall)` | `Adapty.getPaywallProducts(flow)` | | `Adapty.logShowPaywall(paywall)` | `Adapty.logShowFlow(flow)` | | `AdaptyPaywall` | `AdaptyFlow` | | `AdaptyUI.getPaywallView(...)` | `AdaptyUI.getFlowView(...)` | | `AdaptyPaywallView` | `AdaptyFlowView` | | `AdaptyPaywallScreen` (Compose) | `AdaptyFlowScreen` | | `showPaywall(...)` | `showFlow(...)` | | `AdaptyPaywallInsets` | `AdaptyFlowInsets` | | `AdaptyUiEventListener` | `AdaptyFlowEventListener` | | `AdaptyUiDefaultEventListener` | `AdaptyFlowDefaultEventListener` | | `onPaywallShown` / `onPaywallClosed` | `onFlowShown` / `onFlowClosed` | | `onRenderingError` | `onError` | | `Adapty.updateAttribution(attribution, source)` (`source: String`) | `Adapty.updateAttribution(attribution, source)` (`source: AdaptyAttributionSource`) | | `Adapty.setIntegrationIdentifier(key, value)` | `Adapty.setIntegrationIdentifier(AdaptyIntegrationIdentifier)` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` artık bir `AdaptyFlow` alır. Diğer `AdaptyFlowEventListener` metotları (`onProductSelected`, `onPurchaseStarted`, `onPurchaseFinished`, `onPurchaseFailure`, `onRestoreSuccess`, `onRestoreFailure`, `onActionPerformed`, `onAwaitingPurchaseParams`, `onLoadingProductsFailure` ve diğerleri) adlarını ve imzalarını korur. ## Kurulum \{#installation\} `adapty-bom` sürümünü `4.0.0` (veya daha yenisi) olarak ayarlayın ve projeyi senkronize edin. BOM, sizin için uygun `android-sdk` ve `android-ui` sürümlerini otomatik olarak belirler. Bağımlılık tanımlamaları için [Adapty SDK'yı Yükleyin](sdk-installation-android) sayfasına bakın. ## Kaldırılan ve kullanımdan kaldırılan API'ler \{#removed-and-deprecated-apis\} - **`Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized, callback)`** — kaldırıldı. Bu aşırı yükleme v3'te kullanımdan kaldırılmıştı. Aynı seçenekleri bunun yerine `AdaptyPurchaseParameters` üzerinden iletin: ```diff showLineNumbers - Adapty.makePurchase(activity, product, subscriptionUpdateParams, isOfferPersonalized) { result -> /* ... */ } + val params = AdaptyPurchaseParameters.Builder() + .withSubscriptionUpdateParams(subscriptionUpdateParams) + .withOfferPersonalized(isOfferPersonalized) + .build() + Adapty.makePurchase(activity, product, params) { result -> /* ... */ } ``` - **Onboardinglar artık kullanım dışı.** `AdaptyUI.getOnboardingView` ve `AdaptyUI.getOnboardingConfiguration`, 4.0'da `@Deprecated` olarak işaretlendi — onboardinglarınızı [Flow Builder](adapty-flow-builder)'da oluşturulan flow'lara taşıyın. ## Flow'ları getirme \{#fetching-flows\} ### getPaywall + getViewConfiguration → getFlow + getFlowConfiguration Getirme işleminin dönüş türü `AdaptyPaywall`'dan `AdaptyFlow`'a değişiyor; yapılandırma yükleyicisi ise `AdaptyUI.getViewConfiguration`'dan `AdaptyUI.getFlowConfiguration`'a yeniden adlandırılıyor (`AdaptyUI.LocalizedViewConfiguration` yerine `AdaptyUI.FlowConfiguration` döndürüyor). `locale` parametresi, getirme çağrısından `getFlowConfiguration`'a taşınıyor: ```diff showLineNumbers - Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result -> + Adapty.getFlow("YOUR_PLACEMENT_ID") { result -> if (result is AdaptyResult.Success) { - val paywall = result.value - if (!paywall.hasViewConfiguration) return@getPaywall - AdaptyUI.getViewConfiguration(paywall) { configResult -> + val flow = result.value + if (!flow.hasViewConfiguration) return@getFlow + AdaptyUI.getFlowConfiguration(flow, locale = "en") { configResult -> if (configResult is AdaptyResult.Success) { val flowConfiguration = configResult.value } } } } ``` ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` artık `Adapty.getFlow` tarafından döndürülen bir `AdaptyFlow` alıyor: ```diff showLineNumbers - Adapty.getPaywallProducts(paywall) { result -> /* products */ } + Adapty.getPaywallProducts(flow) { result -> /* products */ } ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık `AdaptyPaywall` yerine `AdaptyFlow` alıyor. Etkinlik hâlâ aynı varyasyona karşı kaydedildiğinden, mevcut huni ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder. ```diff showLineNumbers - Adapty.logShowPaywall(paywall) + Adapty.logShowFlow(flow) ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülerken bu metodu çağırmanıza gerek yoktur — Adapty bu görüntülemeleri otomatik olarak takip eder. ## Flow'ları görüntüleme \{#displaying-flows\} ### getPaywallView / AdaptyPaywallView → getFlowView / AdaptyFlowView Factory metodunu ve view türünü yeniden adlandırın, ardından `AdaptyUI.FlowConfiguration`'ı geçirin: ```diff showLineNumbers - val paywallView = AdaptyUI.getPaywallView( - activity, - viewConfiguration, - products, - eventListener, - ) + val flowView = AdaptyUI.getFlowView( + activity, + flowConfiguration, + products, + eventListener, + ) ``` View'ı doğrudan oluşturuyorsanız, show metodu da yeniden adlandırılmıştır: ```diff showLineNumbers - val paywallView = AdaptyPaywallView(activity) - paywallView.showPaywall(viewConfiguration, products, eventListener) + val flowView = AdaptyFlowView(activity) + flowView.showFlow(flowConfiguration, products, eventListener) ``` XML layout'larında view tag'ini güncelleyin: ```diff showLineNumbers - + ``` İsteğe bağlı `personalizedOfferResolver` parametresi `getFlowView` / `showFlow` / `AdaptyFlowScreen`'den kaldırıldı. Kişiselleştirilmiş fiyatlandırmayı belirtmek için `onAwaitingPurchaseParams` aracılığıyla her ürün için ayrı ayrı ayarlayın (`AdaptyPurchaseParameters.Builder().withOfferPersonalized(true)`). Yeni isteğe bağlı `customAssets` parametresi, görselleri ve videoları çalışma zamanında geçersiz kılmanıza olanak tanır — bkz. [Özel asset'ler](android-get-pb-paywalls#customize-assets). ### AdaptyPaywallScreen → AdaptyFlowScreen Jetpack Compose'da composable'ı yeniden adlandırın ve konfigürasyon parametresini güncelleyin: ```diff showLineNumbers - AdaptyPaywallScreen( - viewConfiguration, + AdaptyFlowScreen( + flowConfiguration, products, eventListener, ) ``` ## Olayları Yönetme \{#handling-events\} Olay dinleyicisi `AdaptyUiEventListener`'dan `AdaptyFlowEventListener`'a (ve `AdaptyUiDefaultEventListener`'dan `AdaptyFlowDefaultEventListener`'a) yeniden adlandırıldı. Metot adlarının çoğu değişmedi; yaşam döngüsü ve render callback'leri yeniden adlandırıldı: ```diff showLineNumbers - class YourListener : AdaptyUiDefaultEventListener() { + class YourListener : AdaptyFlowDefaultEventListener() { - override fun onPaywallShown(context: Context) {} - override fun onPaywallClosed() {} + override fun onFlowShown(context: Context) {} + override fun onFlowClosed() {} - override fun onRenderingError(error: AdaptyError, context: Context) {} + override fun onError(error: AdaptyError, context: Context) {} } ``` Mevcut handler gövdelerinde kod değişikliği gerekmez — sadece türü ve override'ları yeniden adlandırın. `onError`, `onRenderingError`'ın tetiklendiği rendering hatalarının yanı sıra diğer satın alma dışı runtime hatalarında da tetiklenir. Callback'lerin tam listesi için bkz. [Flow & paywall olaylarını yönetme](android-handling-events). v4 ayrıca bir `onBackPressed(context): Boolean` callback'i ekler ve varsayılan davranışı sistem geri tuşunun nasıl çalıştığını değiştirir. Önceden geri tuşuna basmak (veya geri gesturı) aktivitenize ya da fragment'ınıza geçer ve genellikle paywall'ı kapatırdı. v4'te varsayılan uygulama bu basışı tüketir; dolayısıyla **sistem geri tuşu artık bir flow'u kendi başına kapatmaz** — flow'un sistem gesturıyla kapatılamadığı iOS davranışıyla aynı hizaya gelir. Kullanıcılara açık bir çıkış yolu sunun (bir **Close** düğmesi veya bir `on_device_back` aksiyonu) ya da eski davranışı geri kazanmak için `onBackPressed`'i `false` döndürecek şekilde geçersiz kılın. Ayrıntılar için [Sistem geri tuşu](android-handling-events#system-back-button) bölümüne bakın. Varsayılan satın alma işleyicisi artık ekranı kapatmayı da durduruyor. v3'te, varsayılan `onPurchaseFinished`, kullanıcının iptal etmediği her tamamlanmış satın almanın (başarılı veya beklemedeki satın alma) ardından paywallı kapatıyordu. v4'te bu işlem hiçbir şey yapmıyor, dolayısıyla **siz kapatana kadar bir flow, satın alma sonrasında açık kalıyor** — bu da iOS davranışıyla örtüşüyor. Bu otomatik kapanmaya güveniyorsanız, satın alma tamamlandığında ekranı kendiniz kapatın. Örnek için [Başarılı, iptal edilmiş veya beklemedeki satın alma](android-handling-events#successful-canceled-or-pending-purchase) konusuna bakın. ## Attribution ve entegrasyon tanımlayıcıları \{#attribution-and-integration-identifiers\} ### updateAttribution `source` parametresi `String` türünden yeni `AdaptyAttributionSource` türüne değişti ve `attribution` artık `Map` türünde (JSON `String` aşırı yüklemesi de mevcuttur). Önceden tanımlanmış kaynaklardan birini kullanın: ```diff showLineNumbers - Adapty.updateAttribution(attribution, "appsflyer") { error -> /* handle the error */ } + Adapty.updateAttribution(attribution, AdaptyAttributionSource.APPSFLYER) { error -> /* handle the error */ } ``` Önceden tanımlanmış kaynaklar: `AdaptyAttributionSource.APPLE_ADS`, `.ADJUST`, `.APPSFLYER`, `.BRANCH`, `.TENJIN`. Diğer kaynaklar için bir dizeden oluşturun: `AdaptyAttributionSource("your_source")`. ### setIntegrationIdentifier `setIntegrationIdentifier(key, value)`, bir veya daha fazla `AdaptyIntegrationIdentifier` değeri alan bir yöntemle değiştirilmiştir. Ham bir string key geçirmek yerine, her tanımlayıcıyı bir kolaylık yöntemiyle oluşturun: ```diff showLineNumbers - Adapty.setIntegrationIdentifier("appsflyer_id", appsFlyerId) { error -> /* handle the error */ } + Adapty.setIntegrationIdentifier(AdaptyIntegrationIdentifier.appsflyerId(appsFlyerId)) { error -> /* handle the error */ } ``` Tek bir çağrıda birden fazla tanımlayıcı ayarlayabilirsiniz: ```kotlin showLineNumbers Adapty.setIntegrationIdentifier( listOf( AdaptyIntegrationIdentifier.appsflyerId(appsFlyerId), AdaptyIntegrationIdentifier.adjustDeviceId(adjustDeviceId), ) ) { error -> /* handle the error */ } ``` Eski her anahtar dizesini ilgili kolaylık metoduyla değiştirin: | v3 anahtarı | v4 `AdaptyIntegrationIdentifier` metodu | |---|---| | `"adjust_device_id"` | `adjustDeviceId(value)` | | `"airbridge_device_id"` | `airbridgeDeviceId(value)` | | `"amplitude_user_id"` | `amplitudeUserId(value)` | | `"amplitude_device_id"` | `amplitudeDeviceId(value)` | | `"appmetrica_device_id"` | `appmetricaDeviceId(value)` | | `"appmetrica_profile_id"` | `appmetricaProfileId(value)` | | `"appsflyer_id"` | `appsflyerId(value)` | | `"branch_id"` | `branchId(value)` | | `"facebook_anonymous_id"` | `facebookAnonymousId(value)` | | `"firebase_app_instance_id"` | `firebaseAppInstanceId(value)` | | `"mixpanel_user_id"` | `mixpanelUserId(value)` | | `"one_signal_subscription_id"` | `oneSignalSubscriptionId(value)` | | `"one_signal_player_id"` | `oneSignalPlayerId(value)` | | `"posthog_distinct_user_id"` | `posthogDistinctUserId(value)` | | `"pushwoosh_hwid"` | `pushwooshHWID(value)` | | `"tenjin_analytics_installation_id"` | `tenjinAnalyticsInstallationId(value)` | `AdaptyIntegrationIdentifier(AdaptyIntegrationIdentifier.Key("custom"), customValue)` şeklinde özel bir `Key` kullanarak bu listede olmayan bir anahtar için identifier'ı doğrudan oluşturabilirsiniz. --- # File: migration-to-android-312 --- --- title: "Adapty Android SDK'yı v3.12'ye Taşıma" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Android SDK v3.12'ye geçiş yapın." --- Adapty SDK 3.12.0'da `logShowOnboarding` metodunu SDK'dan kaldırdık. Bu metodu kullanıyorsanız, SDK'yı 3.12 veya sonraki bir sürüme yükselttiğinizde artık kullanılamayacak. Bunun yerine, [Adapty'nin kodsuz onboarding oluşturucusunda onboarding'ler oluşturabilirsiniz](onboardings). Bu onboarding'lerin analitikleri otomatik olarak takip edilir ve pek çok özelleştirme seçeneğine sahipsiniz. --- # File: migration-to-android-310 --- --- title: "Android Adapty SDK 3.10.0 için Geçiş Rehberi" description: "" --- Adapty SDK 3.10.0, bazı iyileştirmeler getiren büyük bir sürümdür; ancak bu iyileştirmeler sizden birkaç geçiş adımı gerektirebilir: 1. `AdaptyUiPersonalizedOfferResolver` kaldırıldı. Eğer bunu kullanıyorsanız, `onAwaitingPurchaseParams` callback'inde geçirin. 2. Paywall Builder paywallları için `onAwaitingSubscriptionUpdateParams` metod imzasını güncelleyin. ## Satın alma parametreleri callback'ini güncelleme \{#update-purchase-parameters-callback\} `onAwaitingSubscriptionUpdateParams` metodu `onAwaitingPurchaseParams` olarak yeniden adlandırıldı ve artık `AdaptySubscriptionUpdateParameters` yerine `AdaptyPurchaseParameters` kullanıyor. Bu sayede abonelik değiştirme parametrelerini (crossgrade) belirtebilir, fiyatın kişiselleştirilmiş olup olmadığını ([daha fazla bilgi](https://developer.android.com/google/play/billing/integrate#personalized-price)) işaretleyebilir ve diğer satın alma parametrelerini yapılandırabilirsiniz. ```diff showLineNumbers - override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, - ) { - onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) - } + override fun onAwaitingPurchaseParams( + product: AdaptyPaywallProduct, + context: Context, + onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, + ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { + onPurchaseParamsReceived( + AdaptyPurchaseParameters.Builder() + .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) + .withOfferPersonalized(true) + .build() + ) + return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked + } ``` Ek parametreye ihtiyaç duymuyorsanız şunu kullanabilirsiniz: ```kotlin showLineNumbers + override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` --- # File: migration-to-android-sdk-34 --- --- title: "Adapty Android SDK'sını v3.4'e Taşıma" description: "Daha iyi performans ve yeni gelir getirici özellikler için Adapty Android SDK v3.4'e geçin." --- Adapty SDK 3.4.0, tarafınızda geçiş adımları gerektiren iyileştirmeler sunan büyük bir sürümdür. ## Yedek paywall dosyalarını güncelleyin \{#update-fallback-paywall-files\} Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki [mevcut yedek paywallları yeni dosyalarla değiştirin](android-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleyin \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Önceki sürümlerde, Adapty'nin kendi altyapınız üzerinden gerçekleştirilen işlemleri tanıyabilmesi için satın almaları geri yüklemeniz gerekiyordu; çünkü Observer Mode'da Adapty bu işlemlere doğrudan erişemiyordu. Paywall kullanıyorsanız her işlemi başlatan paywall ile elle ilişkilendirmeniz de gerekiyordu. Yeni sürümde, Adapty'nin her işlemi tanıyabilmesi için açıkça bildirmeniz gerekir. Paywall kullanıyorsanız, işlemi kullanılan paywall ile ilişkilendirmek için variation ID'yi de iletmeniz gerekir. :::warning **İşlem raporlamayı atlamayın!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - Adapty.restorePurchases { result -> - if (result is AdaptyResult.Success) { - // success - } - } - - Adapty.setVariationId(transactionId, variationId) { error -> - if (error == null) { - // success - } - } + val transactionInfo = TransactionInfo.fromPurchase(purchase) + + Adapty.reportTransaction(transactionInfo, variationId) { result -> + if (result is AdaptyResult.Success) { + // success + } + } ``` ```diff showLineNumbers - Adapty.restorePurchases(result -> { - if (result instanceof AdaptyResult.Success) { - // success - } - }); - - Adapty.setVariationId(transactionId, variationId, error -> { - if (error == null) { - // success - } - }); + TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); + + Adapty.reportTransaction(transactionInfo, variationId, result -> { + if (result instanceof AdaptyResult.Success) { + // success + } + }); ``` --- # File: migration-to-android330 --- --- title: "Adapty Android SDK'yı v3.3'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Android SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.0, bazı iyileştirmeler getiren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Paywall Builder ile oluşturulmayan paywall'larda satın alma işlemlerini nasıl ele aldığınızı güncelleyin. `USER_CANCELED` ve `PENDING_PURCHASE` hata kodlarını işlemeyi bırakın. İptal edilen bir satın alma artık hata olarak kabul edilmez ve hata olmayan satın alma sonuçlarında görünecektir. 2. Paywall Builder ile oluşturulan paywall'lar için `onPurchaseCanceled` ve `onPurchaseSuccess` olaylarını yeni `onPurchaseFinished` olayıyla değiştirin. Bu değişiklik aynı nedenle yapılmaktadır: iptal edilen satın almalar artık hata olarak değerlendirilmez ve hata olmayan satın alma sonuçlarına dahil edilir. 3. Paywall Builder paywallları için `onAwaitingSubscriptionUpdateParams` metot imzasını değiştirin. 4. Dosya URI'sini doğrudan geçiriyorsanız yedek paywall sağlamak için kullanılan metodu güncelleyin. 5. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. ## Satın alma işlemini güncelleme \{#update-making-purchase\} Daha önce iptal edilen ve beklemedeki satın almalar hata olarak değerlendirilir ve sırasıyla `USER_CANCELED` ve `PENDING_PURCHASE` kodları döndürülürdü. Artık iptal edilen, başarılı ve beklemedeki satın almaları belirtmek için yeni bir `AdaptyPurchaseResult` sınıfı kullanılmaktadır. Satın alma kodunu aşağıdaki şekilde güncelleyin: ~~~diff Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { - val info = result.value - val profile = info?.profile - - if (profile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true) { - // Grant access to the paid features - } + when (val purchaseResult = result.value) { + is AdaptyPurchaseResult.Success -> { + val profile = purchaseResult.profile + if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { + // Grant access to the paid features + } + } + + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash + } + } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ~~~ Tam kod örneği için [Mobil uygulamada satın alma yapma](android-making-purchases#make-purchase) sayfasına göz atın. ## Paywall Builder satın alma olaylarını değiştirme \{#modify-paywall-builder-purchase-events\} 1. `onPurchaseFinished` olayı ekleyin: ```diff showLineNumbers + public override fun onPurchaseFinished( + purchaseResult: AdaptyPurchaseResult, + product: AdaptyPaywallProduct, + context: Context, + ) { + when (purchaseResult) { + is AdaptyPurchaseResult.Success -> { + // Grant access to the paid features + } + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash) + } + } + } ``` Tam kod örneği için [Başarılı, iptal edilen veya beklemedeki satın alma](android-handling-events#successful-canceled-or-pending-purchase) bölümüne ve olay açıklamasına bakın. 2. `onPurchaseCancelled` olayının işlenmesini kaldırın: ```diff showLineNumbers - public override fun onPurchaseCanceled( - product: AdaptyPaywallProduct, - context: Context, - ) {} ``` 3. `onPurchaseSuccess` ifadesini kaldırın: ```diff showLineNumbers - public override fun onPurchaseSuccess( - profile: AdaptyProfile?, - product: AdaptyPaywallProduct, - context: Context, - ) { - // Your logic on successful purchase - } ``` ## `onAwaitingSubscriptionUpdateParams` metodunun imzasını değiştirin \{#change-the-signature-of--onawaitingsubscriptionupdateparams-method\} Artık başka bir abonelik aktifken yeni bir abonelik satın alınırsa, yeni aboneliğin mevcut aktif aboneliğin yerini alması gerekiyorsa `onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters...))` çağırın; aktif aboneliğin yerinde kalması ve yeni aboneliğin ayrı olarak eklenmesi gerekiyorsa `onSubscriptionUpdateParamsReceived(null)` çağırın: ```diff showLineNumbers - public override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - ): AdaptySubscriptionUpdateParameters? { - return AdaptySubscriptionUpdateParameters(...) - } + public override fun onAwaitingSubscriptionUpdateParams( + product: AdaptyPaywallProduct, + context: Context, + onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, + ) { + onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) + } ``` [Yükseltme aboneliği](android-handling-events#upgrade-subscription) doküman bölümüne bakarak son kod örneğini inceleyebilirsiniz. ## Yedek paywall'ları güncelleme \{#update-providing-fallback-paywalls\} Yedek paywall'ları sağlamak için dosya URI'si kullanıyorsanız, bunu aşağıdaki şekilde güncelleyin: ```diff showLineNumbers val fileUri: Uri = // Get the URI for the file with fallback paywalls - Adapty.setFallbackPaywalls(fileUri, callback) + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback) ``` ```diff showLineNumbers Uri fileUri = // Yedek paywall'lar için dosyanın URI'sını al - Adapty.setFallbackPaywalls(fileUri, callback); + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback); ``` ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleme \{#update-third-party-integration-sdk-configuration\} Adapty Android SDK 3.3.0 ve sonraki sürümlerle entegrasyonların düzgün çalışmasını sağlamak için aşağıdaki bölümlerde açıklandığı şekilde entegrasyon SDK yapılandırmalarınızı güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. ```diff showLineNumbers - Adjust.getAttribution { attribution -> - if (attribution == null) return@getAttribution - - Adjust.getAdid { adid -> - if (adid == null) return@getAdid - - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST, adid) { error -> - // Handle the error - } - } - } + Adjust.getAdid { adid -> + if (adid == null) return@getAdid + + Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error -> + if (error != null) { + // Handle the error + } + } + } + + Adjust.getAttribution { attribution -> + if (attribution == null) return@getAttribution + + Adapty.updateAttribution(attribution, "adjust") { error -> + if (error != null) { + // Handle the error + } + } + } ``` ```diff showLineNumbers val config = AdjustConfig(context, adjustAppToken, environment) config.setOnAttributionChangedListener { attribution -> attribution?.let { attribution -> - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST) { error -> + Adapty.updateAttribution(attribution, "adjust") { error -> if (error != null) { // Handle the error } } } } Adjust.onCreate(config) ``` ### AirBridge Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge) bölümüne bakın. ```diff showLineNumbers Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback() { override fun onSuccess(result: String) { - val params = AdaptyProfileParameters.Builder() - .withAirbridgeDeviceId(result) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error -> + if (error != null) { + // Handle the error + } + } } override fun onFailure(throwable: Throwable) { } }) ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) bölümüne bakın. ```diff showLineNumbers // For Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeDeviceId = amplitude.store.deviceId val amplitudeUserId = amplitude.store.userId // - val params = AdaptyProfileParameters.Builder() - .withAmplitudeDeviceId(amplitudeDeviceId) - .withAmplitudeUserId(amplitudeUserId) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### AppMetrica Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppMetrica entegrasyonu için SDK yapılandırması](appmetrica#sdk-configuration) sayfasına bakın. ```diff showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceId = result?.deviceId ?: return - val params = AdaptyProfileParameters.Builder() - .withAppmetricaDeviceId(deviceId) - .withAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID") - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId) { error -> + if (error != null) { + // Handle the error + } + } + + Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error -> + if (error != null) { + // Handle the error + } + } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { // Handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID)) ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) sayfasına bakın. ```diff showLineNumbers val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener { override fun onConversionDataSuccess(conversionData: Map) { - Adapty.updateAttribution( - conversionData, - AdaptyAttributionSource.APPSFLYER, - AppsFlyerLib.getInstance().getAppsFlyerUID(context) - ) { error -> - if (error != null) { - // Handle the error - } - } + val uid = AppsFlyerLib.getInstance().getAppsFlyerUID(context) + Adapty.setIntegrationIdentifier("appsflyer_id", uid) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.updateAttribution(conversionData, "appsflyer") { error -> + if (error != null) { + // Handle the error + } + } } } ``` ### Branch Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırması](branch#connect-your-app-to-branch) bölümüne bakın. ```diff showLineNumbers // Login and update attribution Branch.getAutoInstance(this) .setIdentity("YOUR_USER_ID") { referringParams, error -> referringParams?.let { data -> - Adapty.updateAttribution(data, AdaptyAttributionSource.BRANCH) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.updateAttribution(data, "branch") { error -> + if (error != null) { + // Handle the error + } + } } } // Logout Branch.getAutoInstance(context).logout() ``` ### Facebook Ads Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Facebook Ads entegrasyonu için SDK yapılandırması](facebook-ads#connect-your-app-to-facebook-ads) bölümüne bakın. ```diff showLineNumbers - val builder = AdaptyProfileParameters.Builder() - .withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context)) - - Adapty.updateProfile(builder.build()) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier( + "facebook_anonymous_id", + AppEventsLogger.getAnonymousAppDeviceGUID(context) + ) { error -> + if (error != null) { + // Handle the error + } + } ``` ### Firebase ve Google Analytics \{#firebase-and-google-analytics\} Aşağıda gösterildiği gibi mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers // After Adapty.activate() FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId -> - Adapty.updateProfile( - AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build() - ) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error -> + if (error != null) { + // Handle the error + } + } } ``` ```diff showLineNumbers // After Adapty.activate() - FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build(); - - Adapty.updateProfile(params, error -> { - if (error != null) { - // Handle the error - } - }); - }); + FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> { + if (error != null) { + // Handle the error + } + }); + }); ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonuna yönelik SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın. ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withMixpanelUserId(mixpanelAPI.distinctId) - .build() - - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [OneSignal entegrasyonunda SDK yapılandırması](onesignal#sdk-configuration) bölümüne bakın. ```diff showLineNumbers // SubscriptionID val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver { override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) { - val params = AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.current.id) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error -> if (error != null) { // Handle the error } } } } ``` ```diff showLineNumbers // SubscriptionID IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.getCurrent().getId()) - .build(); - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> { if (error != null) { // Handle the error } }); }; ``` ```diff showLineNumbers // PlayerID val osSubscriptionObserver = OSSubscriptionObserver { stateChanges -> stateChanges?.to?.userId?.let { playerId -> - val params = AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error -> if (error != null) { // Handle the error } - } } } ``` ```diff showLineNumbers // PlayerID OSSubscriptionObserver osSubscriptionObserver = stateChanges -> { OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null; String playerId = to != null ? to.getUserId() : null; if (playerId != null) { - AdaptyProfileParameters params1 = new AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build(); - - Adapty.updateProfile(params1, error -> { + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> { if (error != null) { // Handle the error } - }); } }; ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırmasına](pushwoosh#sdk-configuration) bakın. ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().hwid) - .build() - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error -> if (error != null) { // Handle the error } } ``` ```diff showLineNumbers - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().getHwid()) - .build(); - - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> { if (error != null) { // Handle the error } }); ``` --- # File: migration-to-android-sdk-v3 --- --- title: "Adapty Android SDK'yı v3.0'a Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Android SDK v3.0'a geçin." --- Adapty SDK v3.0, yeni ve heyecan verici [Adapty Paywall Builder](adapty-paywall-builder)'ı destekler; bu, paywall oluşturmak için kullanılan kodsuz, kullanıcı dostu aracın yeni sürümüdür. Maksimum esneklik ve zengin tasarım özellikleriyle paywallleriniz çok daha etkili ve kârlı hale gelecek. Adapty SDK'ları bir BoM (Bill of Materials) olarak sunulur; bu sayede uygulamanızdaki Adapty SDK ve AdaptyUI SDK sürümleri tutarlı kalır. v3.0'a geçiş yapmak için kodunuzu aşağıdaki gibi güncelleyin: ```diff showLineNumbers dependencies { ... - implementation 'io.adapty:android-sdk:2.11.5' - implementation 'io.adapty:android-ui:2.11.3' + implementation platform('io.adapty:adapty-bom:3.0.4') + implementation 'io.adapty:android-sdk' + implementation 'io.adapty:android-ui' } ``` ```diff showLineNumbers dependencies { ... - implementation("io.adapty:android-sdk:2.11.5") - implementation("io.adapty:android-ui:2.11.3") + implementation(platform("io.adapty:adapty-bom:3.0.4")) + implementation("io.adapty:android-sdk") + implementation("io.adapty:android-ui") } ``` ```diff showLineNumbers //libs.versions.toml [versions] .. - adapty = "2.11.5" - adaptyUi = "2.11.3" + adaptyBom = "3.0.4" [libraries] .. - adapty = { group = "io.adapty", name = "android-sdk", version.ref = "adapty" } - adapty-ui = { group = "io.adapty", name = "android-ui", version.ref = "adaptyUi" } + adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } + adapty = { module = "io.adapty:android-sdk" } + adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... + implementation(libs.adapty.bom) implementation(libs.adapty) implementation(libs.adapty.ui) } ``` --- # End of Documentation _Generated on: 2026-07-24T13:02:34.238Z_ _Successfully processed: 41/41 files_ # API - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.241Z Total files: 18 --- # File: developer-cli --- --- title: "Developer CLI" description: "Adapty Developer CLI'ya genel bakış." --- **Adapty Developer CLI**, Adapty hesabınızı kontrol panelini açmadan yönetmenizi sağlayan bir komut satırı aracıdır. Terminal veya otomatik ortamlardan erişebileceğiniz temel yapılandırma özelliklerini sunar. **CLI ile yapabilecekleriniz:** - Adapty hesabınızda iOS ve Android uygulamaları oluşturun ve yapılandırın - Access level'ları tanımlayın — uygulamanızın çalışma zamanında kontrol ettiği abonelik katmanları - Ürünler oluşturun ve bunları App Store ile Google Play mağaza kimliklerine eşleyin - Paywall oluşturun ve ürünleri bunlara atayın - SDK aracılığıyla paywall'ları çekmek için placement'ları yapılandırın :::link Bir yapay zeka asistanı veya MCP istemcisi mi kullanıyorsunuz? LLM'lerin CLI ile çalışmasına yardımcı olmak için bir [Adapty CLI skill](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) mevcuttur. ::: --- # File: developer-cli-quickstart --- --- title: "Adapty Developer CLI için hızlı başlangıç kılavuzu" description: "Adapty hesabınızı Developer CLI ile uçtan uca kurun — uygulama oluşturmadan canlı bir placement'a, birkaç komutla." --- :::link Bir yapay zeka asistanı mı kullanıyorsunuz? LLM'lerin CLI ile çalışmasına yardımcı olmak için bir [Adapty CLI skill](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) mevcuttur. ::: Adapty CLI, uygulama yapılandırmanızı tamamen komut satırından kurmanızı sağlar. Terminal araçlarını veya [MCP istemcilerini](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) tercih ediyorsanız [kontrol paneli hızlı başlangıcı](integrate-payments) yerine bunu kullanabilirsiniz. :::note Adapty'yi App Store Connect ve Google Play'e bağlamak, kontrol panelinde tek seferlik bir kurulum gerektiriyor — bu işlem 3. adımda ele alınıyor. ::: Tüm adımların sonunda uygulamanız, access level'ınız, ürününüz, paywall'unuz ve placement'ınız [Adapty kontrol panelinde](https://app.adapty.io) görünür hale gelecek. ## 1. CLI'ı yükleyin \{#1-install-the-cli\} [Node.js](https://nodejs.org/en/download) 18 veya üzeri gereklidir. CLI'ı yüklemek için şu komutu çalıştırın: ```bash npm install -g adapty ``` Ya da doğrudan: ```bash npx adapty auth login ``` ## 2. Kimlik doğrulaması yapın \{#2-authenticate\} CLI'ı Adapty hesabınıza bağlamak için giriş komutunu çalıştırın. ```bash adapty auth login ``` CLI bir tarayıcı sekmesi açar. Terminalde gösterilen kodu tarayıcıda gösterilen kodla eşleştirin, ardından **Authorize** butonuna tıklayın. Kimlik doğrulama tamamlandığında terminal bunu onaylar. ## 3. Uygulamanızı oluşturun \{#3-create-your-app\} Adapty'deki bir uygulama, mobil uygulamanızı temsil eder. Tek bir Adapty uygulaması hem App Store hem de Google Play'e bağlanır — kaç mağazada yayın yaptığınızdan bağımsız olarak yalnızca bir tane oluşturmanız yeterlidir. ```bash adapty apps create --title "My App" --platform ios --platform android --apple-bundle-id com.example.app --google-bundle-id com.example.app ``` ```bash adapty apps create --title "My App" --platform ios --apple-bundle-id com.example.app ``` ```bash adapty apps create --title "My App" --platform android --google-bundle-id com.example.app ``` Komut bir `` döndürür. Bu ID'yi sonraki tüm komutlarda kullanın. :::important Devam etmeden önce uygulamanızı Adapty kontrol panelinden App Store Connect ve Google Play'e bağlayın. Her iki mağazadaki ürün ID'leri 5. adımda gereklidir. - [App Store Connect'i bağlayın](app-store-connection-configuration) - [Google Play'i bağlayın](google-play-store-connection-configuration) ::: ## 4. Bir access level oluşturun (isteğe bağlı) \{#4-create-an-access-level-optional\} [Access level'lar](access-level), kullanıcıların satın alma sonrasında neye erişebileceğini kontrol eder. Uygulamanız, kullanıcının belirli bir ürün satın alıp almadığını kontrol etmek yerine kullanıcının belirli bir access level'a sahip olup olmadığını kontrol eder. Bu sayede uygulama mantığınız belirli ürün ID'lerinden bağımsız hale gelir. Her yeni uygulamayla birlikte otomatik olarak bir `premium` access level oluşturulur. **Çoğu uygulama için bu adımı atlayabilirsiniz.** 5. adımda access level ID olarak `premium` kullanın. Bu komutu yalnızca farklı ürünler farklı kullanıcı grupları için farklı özelliklerin kilidini açıyorsa çalıştırın — örneğin "Basic" ve "Pro" abonelerinin uygulamanın farklı bölümlerine eriştiği durumlarda. ```bash adapty access-levels create --app --sdk-id "pro" --title "Pro" ``` - `--sdk-id`, uygulama kodunuzda bir özelliğin kullanıcıya sunulup sunulmayacağını kontrol etmek için kullanacağınız tanımlayıcıdır (örneğin `if user.hasAccessLevel("pro")`). Bu adımı atlayıp varsayılan access level'ı kullanırsanız `--sdk-id` değeri `premium` olacaktır. - `--title`, Adapty kontrol panelinde kendi referansınız için görünen bir etikettir. Komut bir `` döndürür. ## 5. Bir ürün oluşturun \{#5-create-a-product\} Adapty'de bir [ürün](product), uygulamanızın sattığı her şeyi temsil eder — bir abonelik veya tek seferlik satın alma. App Store Connect ve Google Play'deki öğeler tek bir Adapty ürünü altında gruplanabilir ve tek bir yerden yönetilebilir. Her mağazadaki ürün ID'lerine ihtiyacınız olacak: App Store Connect'ten Apple ürün ID'si, Google Play Console'dan ise Android ürün ID'si ve base plan ID'si. Bunları nerede bulacağınızla ilgili ayrıntılar için [Ürünler](quickstart-products) sayfasına bakın. 4. adımı atladıysanız, `` olarak 3. adımdaki `apps create` komutunun döndürdüğü `default_access_level.id` değerini kullanın. :::important Burada bağladığınız mağaza ürün ID'leri (`--ios-product-id`, `--android-product-id`) oluşturulduktan sonra değiştirilemez. Farklı mağaza ürün ID'leri kullanmak için yeni bir ürün oluşturmanız gerekir. ::: ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --ios-product-id --android-product-id --android-base-plan-id ``` ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --ios-product-id ``` ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --android-product-id --android-base-plan-id ``` Komut bir `` döndürür. ## 6. Bir paywall oluşturun \{#6-create-a-paywall\} [Paywall](paywalls), ürünlerinizi barındıran kapsayıcıdır. Adapty'de paywall'lar, ürünleri kullanıcılara iletmenin tek yoludur. Her ürünün uygulamanızda görünebilmesi için bir paywall içinde olması gerekir. :::important Bir paywall bir placement'a bağlandıktan sonra ürünleri değiştirilemez. Farklı ürünler kullanmak için yeni bir paywall oluşturun ve placement'ı bu yeni paywall'a işaret edecek şekilde güncelleyin. ::: ```bash adapty paywalls create --app --title "My Paywall" --product-id ``` ```bash adapty paywalls create --app --title "My Paywall" --product-id --product-id ``` Komut bir `` döndürür. ## 7. Bir placement oluşturun \{#7-create-a-placement\} [Placement](placements), uygulamanızda paywall gösterdiğiniz noktadır. Uygulama kodunuzda sabit olarak tanımladığınız tek şey placement ID'sidir. Geri kalanı — hangi paywall'ın hangi kullanıcılara gösterileceği — yeni bir uygulama sürümü yayınlamadan kontrol panelinden yönetilir. `--developer-id`, bu noktada hangi paywall'ın görüntüleneceğini Adapty'den sorgularken uygulama kodunuzda referans olarak kullanacağınız dizedir. Konumu tanımlayan bir şey seçin: `"main"`, `"onboarding"` veya `"settings"` gibi. ```bash adapty placements create --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` `--audiences` bayrağı, hangi kullanıcıya hangi paywall'ın gösterileceğini belirler. Yukarıdaki örnekte tek bir varsayılan kitle tanımlanmıştır — bu placement'taki tüm kullanıcılar aynı paywall'ı görür. ## Sırada ne var \{#whats-next\} Tüm varlıklar artık [Adapty Kontrol Paneli](https://app.adapty.io)'nde görünür. Sırada: - [Paywallını tasarla](adapty-paywall-builder) — az önce oluşturduğun paywall'a görsel, düzen ve metin eklemek için no-code Paywall Builder'ı kullan. - [Adapty SDK'yı entegre et](quickstart-sdk) — placement'ı getirip görüntülemek için SDK'yı uygulamana ekle. - Farklı kullanıcı [segmentlerini](segments) farklı paywall'lara yönlendir — tam referansta [`placements update`](developer-cli-reference#adapty-placements-update) ve [`segments list`](developer-cli-reference#adapty-segments-list) bölümlerine bak. --- # File: developer-cli-authentication --- --- title: "Adapty Geliştirici CLI'da Kimlik Doğrulama" description: "Adapty Geliştirici CLI ile nasıl kimlik doğrulaması yapılır." --- :::link Bir yapay zeka asistanı mı kullanıyorsunuz? LLM'lerin CLI ile çalışmasına yardımcı olmak için bir [Adapty CLI becerisi](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) mevcuttur. ::: CLI, Adapty API'sini çağırmak için kimlik doğrulama gerektirir. ## Giriş yapma \{#log-in\} Giriş yapmak için: 1. Terminalinizde şunu çalıştırın: ```bash adapty auth login ``` 2. CLI, `XXXX-XXXX` biçiminde bir doğrulama kodu yazdırır ve tarayıcınızda Adapty Kontrol Paneli'ni açar. 3. Yetkilendirme sayfasında, kodun terminal çıktınızla eşleştiğini onaylayın. 4. **Authorize** düğmesine tıklayın. Tarayıcıda "CLI authorized! You can close this tab." mesajı görünür. 5. Terminale geri döndüğünüzde, CLI kimlik doğrulamasının başarılı olduğunu onaylar. Siz yetkilendirmeden önce kodun süresi dolarsa veya **Deny** seçeneğine tıklarsanız, akışı yeniden başlatmak için şu komutu tekrar çalıştırın: ```bash adapty auth login ``` ## Kimlik doğrulamayı yönetme \{#manage-authentication\} ### Kimlik doğrulama durumunu kontrol etme \{#check-authentication-status\} Mevcut kimlik doğrulama durumunuzu görmek için şunu çalıştırın: ```bash adapty auth status ``` Kimlik doğrulaması yapıldığında, çıktıda e-posta adresiniz, maskelenmiş bir token öneki ve yerel yapılandırma dosyasının yolu gösterilir: ``` Email: you@example.com Token: abcd1234**** Config: ~/.config/adapty/config.json ``` Kimlik doğrulaması yapılmadığında: ``` Not authenticated. Run `adapty auth login`. ``` ### Tokenınızı doğrulama \{#verify-your-token\} Tokenınızın geçerli olduğunu onaylamak ve hesap bilgilerinizi görmek için şunu çalıştırın: ```bash adapty auth whoami ``` `adapty auth status` komutunun aksine, bu komut tokenı doğrulamak için sunucuya canlı bir istek gönderir. ### Çıkış yapma \{#log-out\} Yerel olarak depolanan kimlik bilgilerinizi temizlemek için şunu çalıştırın: ```bash adapty auth logout ``` Bu komut `~/.config/adapty/config.json` dosyasını temizler. Token, süresi dolana kadar sunucu tarafında geçerliliğini korur — hemen geçersiz kılmak istiyorsanız bunun yerine `adapty auth revoke` komutunu kullanın. ### Tokenınızı iptal etme \{#revoke-your-token\} Tokeni sunucuda geçersiz kılmak ve yerel olarak temizlemek için şunu çalıştırın: ```bash adapty auth revoke ``` Bir tokeni tamamen geçersiz kılmak istediğinizde bunu kullanın — örneğin kimlik bilgilerinizin ele geçirilmiş olabileceği durumlarda. İptal ettikten sonra yeniden kimlik doğrulaması yapmak için `adapty auth login` komutunu çalıştırın. ## Token hataları \{#token-errors\} Bir token iptal edilirse veya geçersiz hale gelirse, CLI komutları 401 hatası döndürür. Yeniden kimlik doğrulaması yapmak için şunu çalıştırın: ```bash adapty auth login ``` --- # File: developer-cli-reference --- --- title: "Adapty Developer CLI için tam referans" description: "Tüm Adapty Developer CLI komutları için eksiksiz referans." --- :::link Bir yapay zeka asistanı mı kullanıyorsunuz? LLM'lerin CLI ile çalışmasına yardımcı olmak için bir [Adapty CLI becerisi](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) mevcuttur. ::: Bu makalede tüm Adapty CLI komutları, argümanları, bayrakları ve kabul edilen değerleriyle birlikte listelenmiştir. :::link Kimlik doğrulama kurulumu ve token yönetimi için bkz. [Kimlik doğrulama](developer-cli-authentication). ::: ## Global bayraklar \{#global-flags\} Bu bayraklar tüm komutlarda kullanılabilir. | Bayrak | Açıklama | |---|---| | `--json` | Biçimlendirilmiş metin yerine JSON olarak çıktı verir | | `--help` | Komut yardımını gösterir | Tüm `list` komutları ayrıca sayfalama bayraklarını da kabul eder: | Bayrak | Varsayılan | Açıklama | |---|---|---| | `--page` | `1` | Sayfa numarası | | `--page-size` | `20` | Sayfa başına öğe sayısı (maks: 100) | ## Uygulamalar \{#apps\} Adapty hesabınızdaki uygulamaları yönetin. Kontrol paneli tabanlı yapılandırma için bkz. [Uygulama ayarları](general). ### adapty apps list \{#adapty-apps-list\} Adapty hesabınızdaki tüm uygulamaları listeler. ```bash adapty apps list ``` [Sayfalama bayraklarını](#global-flags) kabul eder. ### adapty apps get \{#adapty-apps-get\} Belirli bir uygulama için ayrıntıları getirir. ```bash adapty apps get ``` | Argüman | Açıklama | |---|---| | `app-id` | Uygulama ID'si (UUID) | ### adapty apps create \{#adapty-apps-create\} Yeni bir uygulama oluşturur. ```bash adapty apps create --title "My App" --platform ios --apple-bundle-id com.example.app ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--title` | Evet | Uygulama başlığı | | `--platform` | Evet | Platform: `ios` veya `android`. İkisi için tekrarlayın: `--platform ios --platform android` | | `--apple-bundle-id` | `--platform ios` ile zorunlu | Apple bundle ID | | `--google-bundle-id` | `--platform android` ile zorunlu | Google bundle ID | ### adapty apps update \{#adapty-apps-update\} Mevcut bir uygulamayı günceller. ```bash adapty apps update --title "New Name" ``` | Argüman | Açıklama | |---|---| | `app-id` | Uygulama ID'si (UUID) | | Bayrak | Açıklama | |---|---| | `--title` | Yeni uygulama başlığı | | `--apple-bundle-id` | Yeni Apple bundle ID | | `--google-bundle-id` | Yeni Google bundle ID | En az bir bayrak zorunludur. `--platform` oluşturulduktan sonra değiştirilemez. ## Access level'lar \{#access-levels\} ### adapty access-levels list \{#adapty-access-levels-list\} Bir uygulamadaki tüm [access level](access-level)'ları listeler. ```bash adapty access-levels list --app ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | [Sayfalama bayraklarını](#global-flags) kabul eder. ### adapty access-levels get \{#adapty-access-levels-get\} Belirli bir [access level](access-level) için ayrıntıları getirir. ```bash adapty access-levels get --app ``` | Argüman | Açıklama | |---|---| | `access-level-id` | Access level ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | ### adapty access-levels create \{#adapty-access-levels-create\} Yeni bir [access level](access-level) oluşturur. ```bash adapty access-levels create --app --sdk-id "pro" --title "Pro" ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--sdk-id` | Evet | Uygulama kodunda erişimi kontrol etmek için kullanılan tanımlayıcı (örneğin, `"pro"` veya `"premium"`) | | `--title` | Evet | Adapty kontrol panelinde görünen etiket | ### adapty access-levels update \{#adapty-access-levels-update\} Mevcut bir [access level](access-level)'ı günceller. ```bash adapty access-levels update --app --title "Pro Access" ``` | Argüman | Açıklama | |---|---| | `access-level-id` | Access level ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Evet | Yeni görünen etiket | `--sdk-id` oluşturulduktan sonra değiştirilemez. ## Ürünler \{#products\} ### adapty products list \{#adapty-products-list\} Bir uygulamadaki tüm [ürünleri](product) listeler. ```bash adapty products list --app ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | [Sayfalama bayraklarını](#global-flags) kabul eder. ### adapty products get \{#adapty-products-get\} Belirli bir [ürün](product) için ayrıntıları getirir. ```bash adapty products get --app ``` | Argüman | Açıklama | |---|---| | `product-id` | Ürün ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | ### adapty products create \{#adapty-products-create\} Yeni bir [ürün](product) oluşturur. :::important Mağaza ürün ID'leri (`--ios-product-id`, `--android-product-id`, `--android-base-plan-id`) oluşturulduktan sonra değiştirilemez. Farklı mağaza ürün ID'leri kullanmak için yeni bir ürün oluşturun. ::: ```bash adapty products create --app --title "Monthly" --access-level-id --period monthly --ios-product-id com.example.monthly ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Evet | Ürün başlığı | | `--access-level-id` | Evet | Bu ürünün kilidi açacağı [access level](access-level) ID'si (UUID) | | `--period` | Evet | Abonelik dönemi: `weekly`, `monthly`, `2_months`, `3_months`, `6_months`, `yearly`, `lifetime` | | `--ios-product-id` | En az bir platform zorunlu | App Store Connect'teki ürün ID'si | | `--android-product-id` | En az bir platform zorunlu | Google Play Console'daki ürün ID'si | | `--android-base-plan-id` | `--period lifetime` olmadığı sürece `--android-product-id` ile zorunlu | Google Play Console'daki temel plan ID'si | ### adapty products update \{#adapty-products-update\} Mevcut bir [ürünü](product) günceller. Mağaza ürün ID'leri (`--ios-product-id`, `--android-product-id`) oluşturulduktan sonra değiştirilemez ve bu komutta kullanılamaz. Farklı mağaza ürün ID'leri kullanmak için yeni bir ürün oluşturun. ```bash adapty products update --app --title "Monthly" --access-level-id ``` | Argüman | Açıklama | |---|---| | `product-id` | Ürün ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Hayır | Ürün başlığı | | `--access-level-id` | Hayır | Bu ürünün kilidi açacağı [access level](access-level) ID'si (UUID) | ## Paywall'lar \{#paywalls\} ### adapty paywalls list \{#adapty-paywalls-list\} Bir uygulamadaki tüm [paywall'ları](paywalls) listeler. ```bash adapty paywalls list --app ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | [Sayfalama bayraklarını](#global-flags) kabul eder. ### adapty paywalls get \{#adapty-paywalls-get\} Belirli bir [paywall](paywalls) için ayrıntıları getirir. ```bash adapty paywalls get --app ``` | Argüman | Açıklama | |---|---| | `paywall-id` | Paywall ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | ### adapty paywalls create \{#adapty-paywalls-create\} Yeni bir [paywall](paywalls) oluşturur. ```bash adapty paywalls create --app --title "Default Paywall" --product-id ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Evet | Paywall başlığı | | `--product-id` | Evet | [Ürün](product) ID'si (UUID). Birden fazla ürün için tekrarlayın: `--product-id --product-id ` | ### adapty paywalls update \{#adapty-paywalls-update\} Mevcut bir [paywall'ın](paywalls) tüm alanlarını değiştirir. :::important Bir paywall placement'a bağlandıktan sonra ürünleri değiştirilemez. Yayındaki bir paywall'da farklı ürünler kullanmak için yeni bir paywall oluşturun ve placement'ı buna yönlendirmek üzere güncelleyin. ::: ```bash adapty paywalls update --app --title "Default Paywall" --product-id ``` Bu komut, tam ürün listesi dahil tüm paywall alanlarını değiştirir. | Argüman | Açıklama | |---|---| | `paywall-id` | Paywall ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Evet | Paywall başlığı | | `--product-id` | Evet | [Ürün](product) ID'si (UUID). Birden fazla ürün için tekrarlayın: `--product-id --product-id ` | ### adapty paywalls placements Belirli bir [paywall](paywalls)'ın şu anda hangi [placement](placements)'larda kullanıldığını listeler. ```bash adapty paywalls placements --app ``` | Argüman | Açıklama | |---|---| | `paywall-id` | Paywall ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | Bir paywall'ı değiştirmeden önce hangi placement'ların etkileneceğini görmek için bu komutu kullanın. ## Placement'lar \{#placements\} ### adapty placements list \{#adapty-placements-list\} Bir uygulamadaki tüm [placement'ları](placements) listeler. ```bash adapty placements list --app ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | [Sayfalama bayraklarını](#global-flags) kabul eder. ### adapty placements get Belirli bir [placement](placements) için ayrıntıları alır. ```bash adapty placements get --app ``` | Argüman | Açıklama | |---|---| | `placement-id` | Placement ID (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID (UUID) | Yanıt bir `audiences` dizisi içerir. Her giriş `{segment_ids, paywall_id, priority}` şeklindedir. Varsayılan kitle `segment_ids: []` değerine ve en yüksek öncelik değerine (en son değerlendirilen) sahiptir. Biçimlendirilmiş insan çıktısı, kolaylık sağlamak amacıyla varsayılan kitleden türetilen üst düzey bir `Paywall ID` de gösterir. `--json` seçeneği ham API şeklini değiştirmeden döndürür. ### adapty placements create Yeni bir [placement](placements) oluşturur. ```bash adapty placements create --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | | `--title` | Evet | Placement başlığı | | `--developer-id` | Evet | Uygulamada bu [placement](placements)'ı talep etmek için kullanılan string tanımlayıcı | | `--audiences` | İkisinden biri | `{segment_ids, paywall_id, priority}` girişlerinden oluşan JSON dizisi. Bkz. [Audiences şekli](#audiences-shape) | | `--paywall-id` | İkisinden biri | **Kullanımdan kalkmış.** [Paywall](paywalls) ID'si (UUID). İstemci tarafında tek bir varsayılan kitleye sarılır | `--audiences` veya `--paywall-id` seçeneklerinden yalnızca birini girin. Her ikisini birden ya da hiçbirini geçmemek hata verir. :::warning `--paywall-id` kullanımdan kaldırılmıştır ve ilerleyen sürümlerde kaldırılacaktır. Kullanıldığında, CLI stderr'e bir uyarı yazdırır ve değeri varsayılan bir kitleye dönüştürür. Yeni otomasyonlar için `--audiences` kullanın. ::: ### adapty placements update Mevcut bir [placement](placements) öğesinin tüm alanlarını değiştirir. ```bash adapty placements update --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` Bu komut, tüm kitle listesi dahil olmak üzere placement'ın tüm alanlarını değiştirir. | Argüman | Açıklama | |---|---| | `placement-id` | Placement ID'si (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID (UUID) | | `--title` | Evet | Placement başlığı | | `--developer-id` | Evet | Uygulamada bu [placement](placements)'ı talep etmek için kullanılan string tanımlayıcı | | `--audiences` | İkisinden biri | `{segment_ids, paywall_id, priority}` girdilerinden oluşan JSON dizisi. Bkz. [Audiences shape](#audiences-shape) | | `--paywall-id` | İkisinden biri | **Kullanımdan kaldırıldı.** [Paywall](paywalls) ID (UUID). Tüm kitlelerin yerini tek bir varsayılan kitleyle değiştirir | :::warning `--paywall-id` parametresini geçmek, placement üzerindeki tüm kitlelerin üzerine yazar. Segmente özel kitleler silinir. Bunları korumak için `--audiences` kullanın ve saklamak istediğiniz tüm girişleri dahil edin. ::: #### Kitle yapısı \{#audiences-shape\} `--audiences` bayrağı bir JSON dizisi alır. Her giriş şunları içerir: | Alan | Tür | Açıklama | |---|---|---| | `segment_ids` | `string[]` | Bu kitle tarafından hedeflenen [segment](segments) ID'leri. Uzunluk 0 veya 1. Boş dizi **varsayılan kitleyi** işaret eder — başka hiçbir segmentle eşleşmeyen kullanıcılar için yedek | | `paywall_id` | `string` | Bu kitleye gösterilen [paywall](paywalls) ID'si (UUID) | | `priority` | `number` | 0 tabanlı, placement içinde benzersiz. Kitleler düşükten yükseğe doğru değerlendirilir; varsayılan kitle en yüksek değere sahip olmalıdır | Bir placement'ın tam olarak bir varsayılan kitlesi olmalıdır. Bir hedefli kitle ve bir varsayılan kitle içeren örnek: ```bash adapty placements update --app --title "Main" --developer-id "main" \ --audiences '[{"segment_ids":[""],"paywall_id":"","priority":0},{"segment_ids":[],"paywall_id":"","priority":1}]' ``` Segment bazlı yönlendirmeyi kaybetmeden bir paywall'ı birden fazla placement'ta değiştirmek için: 1. Etkilenen placement'ları bulun: ```bash adapty paywalls placements --app ``` 2. Her biri için tam `audiences` dizisini okuyun: ```bash adapty placements get --app --json ``` 3. Eşleşen `paywall_id` değerlerini istemci tarafında değiştirin. 4. Değiştirilmiş payload'ı geri yazın: ```bash adapty placements update --app --title "" --developer-id "<developer-id>" --audiences '<modified-payload>' ``` ## Segmentler \{#segments\} [Segmentler](segments) CLI üzerinden yalnızca okunabilir. Oluşturmak ve düzenlemek için [Adapty Kontrol Paneli](https://app.adapty.io)'ni kullanın. Placement kitlelerini oluştururken segment ID'lerini bulmak için bu komutları kullanın. ### adapty segments list Bir uygulama için tüm [segmentleri](segments) listeler. ```bash adapty segments list --app <app-id> ``` | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID'si (UUID) | [Sayfalandırma bayraklarını](#global-flags) kabul eder. ### adapty segments get Belirli bir [segment](segments) için ayrıntıları getirir. ```bash adapty segments get --app <app-id> <segment-id> ``` | Argüman | Açıklama | |---|---| | `segment-id` | Segment ID (UUID) | | Bayrak | Zorunlu | Açıklama | |---|---|---| | `--app` | Evet | Uygulama ID (UUID) | Yanıt `id`, `title` ve `description` alanlarını içerir. Filtre kuralları bu API aracılığıyla gösterilmez. ## Kimlik doğrulama \{#auth\} | Komut | Açıklama | |---|---| | `adapty auth login` | Cihaz akışı ile tarayıcı üzerinden kimlik doğrulama yapar | | `adapty auth logout` | Yerel olarak depolanan kimlik bilgilerini temizler | | `adapty auth whoami` | Token'ı sunucu ile doğrular ve kullanıcı bilgilerini gösterir | | `adapty auth status` | Sunucuya çağrı yapmadan yerel kimlik doğrulama durumunu gösterir | | `adapty auth revoke` | Token'ı sunucu tarafında iptal eder ve yerel olarak temizler | Her komut hakkında ayrıntılı bilgi için bkz. [Kimlik doğrulama](developer-cli-authentication). --- # File: getting-started-with-server-side-api --- --- title: "Sunucu Taraflı API" description: "Adapty'nin abonelik yönetimi için sunucu taraflı API'siyle başlayın." --- :::tip Bir AI kodlama ajanı mı kullanıyorsunuz? Tek sayfada uçtan uca bir tarif için [Backend'inizden abonelik erişimini kontrol etme ve verme](server-side-api-with-ai) konusuna bakın. ::: API ile şunları yapabilirsiniz: 1. Kullanıcının abonelik durumunu kontrol etme. 2. Kullanıcının aboneliğini bir access level ile etkinleştirme. 3. Kullanıcı özelliklerini alma. 4. Kullanıcı özelliklerini ayarlama. 5. Paywall yapılandırmalarını alma ve güncelleme. <img src="/assets/shared/img/server.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note Abonelik olaylarını takip etmek için Adapty'deki [Webhook](webhook) entegrasyonunu kullanın ya da mevcut servisinizle doğrudan entegre edin. ::: ::: ## Durum 1: Web ve mobil arasında aboneleri senkronize etme \{#case-1-sync-subscribers-between-web-and-mobile\} Stripe, ChargeBee veya başka web ödeme sağlayıcıları kullanıyorsanız, abonelerinizi kolayca senkronize edebilirsiniz. İşte nasıl yapacağınız: 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. API üzerinden [abonelik durumunu kontrol edin](api-adapty/operations/getProfile). 3. Kullanıcı ücretsiz planda ise web sitenizde bir paywall gösterin. 4. Başarılı bir ödemenin ardından [abonelik durumunu](api-adapty/operations/setTransaction) API üzerinden Adapty'de güncelleyin. 5. Aboneleriniz mobil uygulamanızla otomatik olarak senkronize olmaya devam eder. ## 2. Durum: Abonelik ver \{#case-2-grant-a-subscription\} :::note Güvenlik nedeniyle, mobil SDK aracılığıyla abonelik veremezsiniz. ::: Google Play ve App Store dışında kendi online mağazanız, Amazon Appstore, Microsoft Store veya başka bir platform üzerinden satış yapıyorsanız, erişim sağlamak ve işlemi analitikte takip etmek için bu işlemleri Adapty ile senkronize etmeniz gerekir. 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. [Adapty Kontrol Paneli'nde ürünleriniz için özel bir mağaza kurun](custom-store). 3. İşlemi [Set transaction](api-adapty/operations/setTransaction) API isteğini kullanarak Adapty ile senkronize edin. ## Durum 3: Access level tanımlama \{#case-3-grant-an-access-level\} Diyelim ki 7 günlük ücretsiz deneme sunan bir promosyon yürütüyorsunuz ve deneyimin platformlar arasında tutarlı olmasını istiyorsunuz. Bunu mobil uygulama ile senkronize etmek için: 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. 7 gün boyunca [premium erişim vermek](api-adapty/operations/grantAccessLevel) için API'yi kullanın. 7 gün sonra abone olmayan kullanıcılar ücretsiz katmana düşürülecektir. ## Durum 4: Kullanıcı özelliklerini ve özel nitelikleri senkronize etme \{#case-4-sync-users-properties-and-custom-attributes\} Kullanıcılarınız için özel nitelikler varsa—örneğin bir dil öğrenme uygulamasında öğrenilen kelime sayısı—bunları da senkronize edebilirsiniz. 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), and [Unity](unity-identifying-users)</InlineTooltip>. 2. API veya SDK aracılığıyla [niteliği güncelleyin](api-adapty/operations/updateProfile). Bu özel nitelikler, segment oluşturmak ve A/B testleri çalıştırmak için kullanılabilir. ## Durum 5: Paywall yapılandırmalarını yönetme \{#case-5-manage-paywall-configurations\} Uygulamanızı yeniden dağıtmadan paywall görünümünü ve davranışını dinamik olarak ayarlamak için [paywall'lardaki remote config'leri güncelleyebilirsiniz](api-adapty/operations/updatePaywall). --- **Sıradaki adımlar:** - [Sunucu tarafı API için yetkilendirme](ss-authorization) ile devam edin - İstekler: - [Profil al](api-adapty/operations/getProfile) - [Profil oluştur](api-adapty/operations/createProfile) - [Profil güncelle](api-adapty/operations/updateProfile) - [Profil sil](api-adapty/operations/deleteProfile) - [Access level ver](api-adapty/operations/grantAccessLevel) - [Access level iptal et](api-adapty/operations/revokeAccessLevel) - [İşlem ayarla](api-adapty/operations/setTransaction) - [Satın almayı doğrula, müşteriye access level sağla ve işlem geçmişini içe aktar](api-adapty/operations/validateStripePurchase) - [Entegrasyon tanımlayıcıları ekle](api-adapty/operations/setIntegrationIdentifiers) - [Paywall al](api-adapty/operations/getPaywall) - [Paywall'ları listele](api-adapty/operations/listPaywalls) - [Paywall güncelle](api-adapty/operations/updatePaywall) --- # File: ss-authorization --- --- title: "Sunucu Taraflı API Yetkilendirme ve İstek Formatı" description: "" --- ## Yetkilendirme \{#authorization\} API isteklerinin kimlik doğrulaması için gizli veya genel API anahtarınızı Authorization başlığı olarak kullanmanız gerekir. Bu anahtarları [**App Settings**](https://app.adapty.io/settings/general) bölümünde bulabilirsiniz. Değerin biçimi `Api-Key {your-secret-api-key}` şeklindedir; örneğin `Api-Key secret_live_...`. :::important API anahtarları uygulamaya özeldir. Birden fazla uygulamanız varsa her biri için farklı anahtarlar kullandığınızdan emin olun. ::: ## İstek formatı \{#request-format\} **Başlıklar** Sunucu taraflı API istekleri belirli başlıklar ve bir JSON gövdesi gerektirir. İsteklerinizi yapılandırmak için aşağıdaki ayrıntıları kullanın. | **Başlık** | **Açıklama** | | --------------------------- | ------------------------------------------------------------ | | **adapty-profile-id** | <p>Kullanıcının Adapty profil ID'si. [Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> ilgili profil sayfasındaki **Adapty ID** alanında görüntülenir.</p><p>**adapty-customer-user-id** ile birbirinin yerine kullanılabilir; ikisinden birini tercih edebilirsiniz.</p> | | **adapty-customer-user-id** | <p>Kullanıcının sisteminizde kayıtlı ID'si. [Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> ilgili profil sayfasındaki **Customer user ID** alanında görüntülenir.</p><p>**adapty-profile-id** ile birbirinin yerine kullanılabilir; ikisinden birini tercih edebilirsiniz.</p><p>⚠️ Yalnızca uygulama kodunuzda Adapty SDK aracılığıyla kullanıcıları <InlineTooltip tooltip="identify users in your app">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip> şeklinde tanımladığınızda çalışır.</p> | | **adapty-platform** | (isteğe bağlı) Uygulamanın yüklü olduğu cihazın platformunu belirtir. Bu parametreyi, [Installation Meta](server-side-api-objects#installation-meta) nesnesini güncellerken [Create profile](api-adapty/operations/createProfile) ve [Update profile](api-adapty/operations/updateProfile) isteklerinde ayarlamanızı öneririz; çünkü bu değer kullanıcının kullandığı cihaza bağlıdır ve tek bir kullanıcının birden fazla cihazı olabilir. Olası değerler: `iOS`, `macOS`, `iPadOS`, `visionOS`, `Android` veya `web`. | | **Content-Type** | API'nin isteği işleyebilmesi için `application/json` olarak ayarlayın. | **Gövde** API, istek için gerekli verileri içeren JSON formatında bir gövde bekler. ## Hız Sınırları \{#rate-limits\} Kısıtlamayla karşılaşmamak için istek sayısını (uygulama başına) dakikada 40.000'in altında tutun. Bu sınır aşılırsa, tüm kullanıcılar için optimum performansı korumak amacıyla sistem yavaşlayabilir ya da gelen istekleri geçici olarak engelleyebilir. ## API anahtarlarını yenileme \{#rotate-api-keys\} Gizli API anahtarlarını yenilemek istiyorsanız: 1. **Settings → General** bölümünde **Generate new key** seçeneğine tıklayın, ardından eski anahtarın yanındaki çöp kutusu simgesine tıklayın. 2. Uygulamanızda kullanılan anahtarı güncelleyin. --- **Sıradaki adım: istekler:** - [Profil al](api-adapty/operations/getProfile) - [Profil oluştur](api-adapty/operations/createProfile) - [Profil güncelle](api-adapty/operations/updateProfile) - [Profil sil](api-adapty/operations/deleteProfile) - [Access level ver](api-adapty/operations/grantAccessLevel) - [Access level iptal et](api-adapty/operations/revokeAccessLevel) - [İşlem ayarla](api-adapty/operations/setTransaction) - [Satın almayı doğrula, müşteriye access level ver ve işlem geçmişini içe aktar](api-adapty/operations/validateStripePurchase) - [Paywall al](api-adapty/operations/getPaywall) - [Paywall'ları listele](api-adapty/operations/listPaywalls) - [Paywall güncelle](api-adapty/operations/updatePaywall) --- # File: server-side-api-specs --- --- title: "Sunucu taraflı API istekleri" description: "Gelişmiş entegrasyon için Adapty'nin sunucu taraflı API özelliklerini keşfedin." --- Adapty'nin sunucu taraflı API'si, abonelik verilerinize programlı olarak erişmenizi ve bunları yönetmenizi sağlayarak mevcut hizmetleriniz ve altyapınızla sorunsuz entegrasyon sunar. İster platformlar arasında veri senkronizasyonu yapın, ister access level tanımlayın, ister Stripe'ta satın alımları doğrulayın; bu API, sistemlerinizi senkronize tutmak ve kullanıcılarınızın bağlantısını sürdürmek için gereken tüm araçları sunar. ## Postman koleksiyonu ve ortamı \{#postman-collection-and-environment\} Sunucu taraflı API'yi daha kolay kullanabilmeniz için bir Postman koleksiyonu ve Postman'e indirip aktarabileceğiniz bir ortam dosyası hazırladık. - **İstek Koleksiyonu**: Adapty sunucu taraflı API'sinde mevcut tüm istekleri içerir. Ortamda tanımlayabileceğiniz değişkenleri kullandığını unutmayın. - **Ortam**: Değerleri bir kez tanımlayabileceğiniz değişkenlerin listesini içerir. İşleri kolaylaştırmak için sunucu taraflı API, web API ve analiz dışa aktarma API'si için birleşik bir ortam hazırladık. Bu ortamı etkinleştirdikten sonra Postman, tanımlanan değişken değerlerini isteklerinizde otomatik olarak kullanacaktır. :::tip [Koleksiyonu ve ortamı indirin](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_server_side_API_postman_collection.zip) ::: Koleksiyon ve ortamı Postman'e nasıl aktaracağınız hakkında bilgi almak için lütfen [Postman belgelerine](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/) bakın. ### Kullanılan değişkenler \{#variables-used\} İş akışınızı basitleştirmek için sunucu taraflı API, web API ve analiz dışa aktarma API'si için birleşik bir ortam oluşturduk. Aşağıda sunucu taraflı API'ye özgü değişkenler yer almaktadır: | Değişken | Açıklama | Örnek Değer | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | secret_api_key | [**App settings**](https://app.adapty.io/settings/general) içindeki **Secret key** alanında bulabilirsiniz. | `secret_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | | adapty-customer-user-id | Sisteminizde kullandığınız kullanıcı kimliği. Adapty Kontrol Paneli'nde Profil'in **Customer user ID** alanında bulabilirsiniz. | `john.doe@example.com` | | adapty-profile-id | Adapty tarafından atanan kullanıcı kimliği. Adapty Kontrol Paneli'nde Profil'in **Adapty ID** alanında bulabilirsiniz. | `3286abd3-48b0-4e9c-a5f6-ac0a006333a6` | | Adapty-platform | Kullanıcının uygulamanız için kullandığı platform. Olası değerler: `iOS`, `macOS`, `iPadOS`, `visionOS`, `Android`, `web`. | `iOS` | | stripe_token | Abonelik (`sub_XXX`) veya Ödeme Niyeti (`pi_XXX`) gibi benzersiz bir satın alımı temsil eden Stripe nesnesinin token'ı. | `sub_1JY8xLLy6P12345a` | **Sırada ne var: İstekler:** - [Profil al](api-adapty/operations/getProfile) - [Profil oluştur](api-adapty/operations/createProfile) - [Profil güncelle](api-adapty/operations/updateProfile) - [Profil sil](api-adapty/operations/deleteProfile) - [Access level ver](api-adapty/operations/grantAccessLevel) - [Access level iptal et](api-adapty/operations/revokeAccessLevel) - [İşlem ayarla](api-adapty/operations/setTransaction) - [Satın almayı doğrula, müşteriye access level sağla ve işlem geçmişini içe aktar](api-adapty/operations/validateStripePurchase) - [Entegrasyon tanımlayıcıları ekle](api-adapty/operations/setIntegrationIdentifiers) - [Paywall al](api-adapty/operations/getPaywall) - [Paywall'ları listele](api-adapty/operations/listPaywalls) - [Paywall güncelle](api-adapty/operations/updatePaywall) - [Sanal para birimi işlemi oluştur](api-adapty/operations/createVirtualCurrencyTransaction) - [Sanal para birimi işlemlerini listele](api-adapty/operations/listVirtualCurrencyTransactions) - [Sanal para birimi bakiyelerini listele](api-adapty/operations/listVirtualCurrencyBalances) --- # File: api-guides --- --- title: "API kılavuzları" description: "Sunucu taraflı API kullanarak belirli görevleri nasıl gerçekleştireceğinizi öğrenin." --- Bu bölümde, farklı kullanım senaryolarını ele alan ve sunucu taraflı API ile Adapty SDK kullanarak belirli görevleri gerçekleştirmenize yardımcı olan kılavuzları bulabilirsiniz. <CustomDocCardList /> --- # File: sync-subscribers-from-web --- --- title: "Web ve mobil arasında satın almaları senkronize etme" description: "Web ve mobilde aboneleri senkronize edin." --- Kullanıcılarınız ürünleri **web siteniz** üzerinden satın alabiliyorsa, access level'larını **mobil uygulamanızla** otomatik olarak senkronize edebilirsiniz. Bu kılavuzda, bunu Adapty API ve SDK kullanarak nasıl yapacağınızı öğreneceksiniz. #### Örnek kullanım senaryosu Diyelim ki uygulamanızda kullanıcılar hem mobilde hem de web'de ücretsiz plana kaydolabiliyor. Web sitenizde Stripe veya Chargebee aracılığıyla Premium plana geçişe izin veriyorsunuz. Bir kullanıcı web'de abone olduğunda, onlara mobil uygulamada hemen Premium erişim vermek istiyorsunuz — bekleme ya da yeniden giriş yapmadan. Adapty tam da bunu otomatikleştirmenize yardımcı olur. ## Adım 1. Kullanıcıları tanımlayın \{#step-1-identify-users\} Adapty, kullanıcıları platformlar arası tanımlamak için `customer_user_id` kullanır. Bu ID'yi bir kez oluşturmanız ve hem mobil SDK'nıza hem de web arka ucunuza iletmeniz gerekir. ### Web'den kayıt \{#sign-up-from-web\} Kullanıcılarınız web sitenizde kayıt olduğunda, sunucu taraflı API kullanarak Adapty'de onlar için bir profil oluşturmanız gerekir. Yöntem referansını [buradan](api-adapty/operations/createProfile) inceleyebilirsiniz. ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/profile/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_CUSTOMER_USER_ID' ``` ### Uygulamadan kayıt \{#sign-up-from-app\} Kullanıcılarınız uygulamadan ilk kez kayıt olduğunda, customer user ID'yi SDK aktivasyonu sırasında iletebilir ya da SDK'yı kayıt aşamasından önce aktive ettiyseniz yeni bir profil oluşturup customer user ID atamak için `identify` metodunu kullanabilirsiniz. :::important SDK aktivasyonundan sonra yeni kullanıcıları tanımlıyorsanız, SDK önce anonim bir profil oluşturur; çünkü herhangi bir profil olmadan çalışamaz. Ardından kullanıcıyı tanımlayıp yeni bir customer user ID atadığınızda yeni bir profil oluşturulur. Bu davranış tamamen normaldir ve analitik doğruluğunu etkilemez. Daha fazla bilgi için [buraya](ios-quickstart-identify) bakın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## 2. Adım. API üzerinden abonelik durumunu kontrol edin \{#step-2-check-subscription-status-via-api\} Kullanıcı web sitenizde oturum açtığında, API ile Adapty profilini çekin. Kullanıcının aktif bir aboneliği yoksa paywall gösterebilirsiniz. Yöntem referansını [buradan](api-adapty/operations/getProfile) inceleyebilirsiniz. ```bash curl --request GET \ --url https://api.adapty.io/api/v2/server-side-api/profile/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'adapty-customer-user-id: YOUR_USER_ID' \ ``` ## 3. Adım. Web sitenizde paywall gösterin \{#step-3-display-a-paywall-on-your-website\} Web sitenizde ücretsiz plan kullanıcılarına paywall gösterin. Herhangi bir ödeme sağlayıcısı kullanabilirsiniz (Stripe, Chargebee, LemonSqueezy vb.). ## 4. Adım. Adapty'de abonelik durumunu güncelleyin \{#step-4-update-subscription-status-in-adapty\} Web sitenizde ödeme tamamlandıktan sonra, Adapty API'ını çağırarak kullanıcının satın aldığı ürüne göre access level'ını güncelleyin. Yöntem referansını [buradan](api-adapty/operations/grantAccessLevel) inceleyebilirsiniz. ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_USER_ID' \ --data '{ "access_level_id": "YOUR_ACCESS_LEVEL" }' ``` ## 5. Adım. Uygulamada durumu senkronize edin \{#step-5-sync-status-in-the-app\} Kullanıcı mobil uygulamanızı açtığında, güncel profili çekin ve ücretli özelliklerin kilidini açın. Profillerini ya manuel olarak almanız ya da otomatik senkronize etmeniz gerekir. Ardından profilden access level'ı alın. Aşağıda profili nasıl alacağınızı ve durumunu nasıl kontrol edeceğinizi görebilirsiniz. Daha fazla ayrıntı için [buraya](ios-check-subscription-status) gidin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: sync-purchases-from-custom-stores --- --- title: "Özel mağazalardan işlemleri senkronize etme" description: "Erişim sağlamak ve geliri takip etmek için özel mağazalardaki işlemleri Adapty ile senkronize edin." --- Amazon Appstore, Microsoft Store veya kendi ödeme platformunuz gibi **özel mağazalar** üzerinden abonelik ya da uygulama içi satın alma sunuyorsanız, access level yönetimini otomatikleştirmek ve geliri analizlerinizde takip etmek için bu işlemleri Adapty ile senkronize edebilirsiniz. Bu kılavuzda, özel mağaza satın almalarını SDK ve API aracılığıyla Adapty'ye nasıl bağlayacağınızı öğreneceksiniz. #### Örnek kullanım senaryosu Diyelim ki uygulamanızı Amazon Appstore'da dağıtıyorsunuz ya da doğrudan satış için kendi web mağazanızı kurduğunuz. Bir kullanıcı bu platformlardan birinde satın alma işlemini tamamladığında şunları yapmak istiyorsunuz: - Kullanıcıya mobil uygulamanızdaki premium özelliklere otomatik olarak erişim vermek - İşlemi, App Store ve Google Play gelirinizin yanı sıra Adapty analizlerinde de takip etmek - Diğer abonelikler gibi entegrasyonları ve webhook'ları tetiklemek İşte bu entegrasyon tam olarak bunu sağlar. ## 1. Adım. Kullanıcıları tanımlayın \{#step-1-identify-users\} Adapty, platformlar arası kullanıcı tanımlaması için `customer_user_id` kullanır. Bu ID'yi bir kez oluşturup hem mobil SDK'ya hem de web arka ucunuza iletmeniz gerekir. Kullanıcılar uygulamadan ilk kez kayıt olduğunda, SDK aktivasyonu sırasında customer user ID'yi geçirebilirsiniz. Adapty SDK'yı kayıt aşamasından önce aktive ettiyseniz, yeni bir profil oluşturmak ve buna customer user ID atamak için `identify` metodunu kullanın. :::important SDK aktivasyonundan sonra yeni kullanıcıları tanımlarsanız SDK önce anonim bir profil oluşturur (profil olmadan çalışamaz). `identify` metodunu customer user ID ile çağırdığınızda yeni bir profil oluşturulur. Bu davranış normaldir ve analiz doğruluğunu etkilemez. Daha fazla bilgi için [buraya](ios-quickstart-identify) bakın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## 2. Adım. Adapty Kontrol Paneli'nde özel mağaza ürünleri oluşturun \{#step-2-create-products-in-a-custom-store-in-adapty-dashboard\} Adapty'nin özel mağaza işlemlerini ürünlerinizle eşleştirebilmesi için ürünleri eklemeniz ve bunlara özel mağaza bilgilerini tanımlamanız gerekir. 1. Adapty Kontrol Paneli'nde sol menüden [**Products**](https://app.adapty.io/settings/general) bölümüne gidin ve **Create product** düğmesine tıklayın. Ya da mevcut bir ürüne tıklayarak düzenleyin. 2. Ürünü satın alan kullanıcılara vermek istediğiniz [access level](access-level) seçeneğini belirlediğinizden emin olun. 3. **+** düğmesine tıklayın ve **Add a custom store** seçeneğini seçin. 4. **Create new custom store** seçeneğine tıklayın. 5. Mağazanıza bir ad (örn. "Amazon Appstore", "Microsoft Store" veya "Web Store") ve ID verin. **Create custom store** düğmesine tıklayın. 6. Ardından ürünü özel mağazayla ilişkilendirmek için **Save changes** düğmesine tıklayın. 7. Ürünü o mağazadaki bir ürünle eşleştirmek için **Store product ID** alanını doldurun ve **Save** düğmesine tıklayın. ## 3. Adım. API aracılığıyla işlemleri senkronize edin \{#step-3-sync-transactions-via-api\} Özel mağazanızda bir satın alma tamamlandığında, sunucu tarafı API'yi kullanarak bunu Adapty'ye senkronize etmeniz gerekir. Bu API çağrısı şunları yapar: - İşlemi Adapty'ye kaydeder - Kullanıcıya karşılık gelen access level'ı atar - Yapılandırdığınız entegrasyonları ve webhook'ları tetikler - İşlemin analizlerinizde görünmesini sağlar Metodun tam referansına [buradan](api-adapty/operations/setTransaction) ulaşabilirsiniz. ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/set/transaction/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_CUSTOMER_USER_ID' \ --data '{ "purchase_type": "PRODUCT_PERIOD", "store": "YOUR_CUSTOM_STORE", "environment": "production", "store_product_id": "YOUR_STORE_PRODUCT_ID", "store_transaction_id": "STORE_TRANSACTION_ID", "store_original_transaction_id": "ORIGINAL_TRANSACTION_ID", "price": { "country": "COUNTRY_CODE", "currency": "CURRENCY_CODE", "value": "YOUR_PRICE" }, "purchased_at": "2024-01-15T10:30:00Z" }' ``` :::important Önemli parametreler: - **store**: 2. Adım'daki özel mağazanızın ID'si - **store_product_id**: 2. Adım'daki mağaza ürün ID'si - **store_transaction_id**: Bu işlem için benzersiz bir tanımlayıcı - **purchased_at**: Satın almanın gerçekleştiği ISO 8601 zaman damgası - **price**: Kullanıcının ödediği tutar ::: ## 4. Adım. Uygulamada erişimi doğrulayın \{#step-4-verify-access-in-the-app\} İşlem senkronize edildiğinde, kullanıcının profili yeni access level ile otomatik olarak güncellenir. Kullanıcı mobil uygulamanızı açtığında, abonelik durumunu kontrol etmek ve premium özelliklerin kilidini açmak için profilini çekin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: grant-access-level --- --- title: "Access level'ları manuel olarak ver" description: "Belirli kullanıcılara veya kullanıcı gruplarına ücretli özelliklerin kilidini manuel olarak açın" --- Belirli kullanıcılara veya kullanıcı gruplarına **premium özellikleri manuel olarak açmak** istiyorsanız, bunu Adapty API aracılığıyla yapabilirsiniz. Bu yöntem; promosyon kampanyaları, yatırımcı erişimi veya özel müşteri destek senaryoları için oldukça kullanışlıdır. Bu kılavuzda, kullanıcıları nasıl tanımlayacağınızı ve onlara access level'ları programatik olarak nasıl vereceğinizi öğreneceksiniz. #### Örnek kullanım senaryoları \{#sample-use-cases\} - **Promo kodları**: Kullanıcılar uygulamanızda geçerli bir promo kodu girdiğinde, onlara otomatik olarak premium özelliklere erişim verin. - **Yatırımcı/beta tester erişimi**: Özel nitelikleri kontrol ederek yatırımcılara veya beta testçilere premium erişim sağlayın. :::note **Google Play promosyon kodları**: Google Play promosyon kodu kullanılarak yapılan bir satın alma, `orderId` olmadan gelebilir. Adapty'nin tek seferlik (abonelik dışı) satın alma doğrulaması bir `orderId` gerektirdiğinden, bu kodla yapılan satın almalar otomatik olarak doğrulanmaz veya erişim verilmez. Aşağıdaki adımlarla erişimi manuel olarak verin — Sunucu Tarafı API'si `orderId`'ye bağlı değildir. ::: ## Adım 1. Kullanıcıları tanımlayın \{#step-1-identify-users\} Adapty, kullanıcıları platformlar ve cihazlar arasında tanımlamak için `customer_user_id` kullanır. Bu, kullanıcıların uygulamayı yeniden yükledikten veya cihaz değiştirdikten sonra da erişimlerini korumasını sağlamak açısından kritik öneme sahiptir. Bu ID'yi bir kez oluşturmanız yeterlidir. Kullanıcılar uygulamadan ilk kez kayıt olduğunda, SDK aktivasyonu sırasında customer user ID'yi iletebilir ya da SDK kaydolmadan önce aktif edildiyse `identify` metodunu kullanabilirsiniz. :::important SDK aktivasyonundan sonra yeni kullanıcıları tanımlarsanız, SDK önce anonim bir profil oluşturur (onsuz çalışamaz). `identify`'ı bir customer user ID ile çağırdığınızda yeni bir profil oluşturulur. Bu davranış normaldir ve analitik doğruluğunu etkilemez. Daha fazla bilgi için [buraya bakın](ios-quickstart-identify). ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## Adım 2. API aracılığıyla access level verin \{#step-2-grant-access-level-via-api\} Bir kullanıcı `customer_user_id` ile tanımlandıktan sonra, sunucu taraflı API'yi kullanarak onlara access level verebilirsiniz. Bu API çağrısı, kullanıcıya gerçekten ödeme yapmadan ücretli özelliklere erişebilmesi için access level tanımlar. Metodun tam referansına [buradan](api-adapty/operations/grantAccessLevel) ulaşabilirsiniz. :::tip Adapty kontrol panelinde özel bir nitelik (ör. Beta tester veya Investor) ekleyerek kullanıcı erişimini yönetebilirsiniz. Uygulamanız başlatıldığında, erişimi otomatik olarak vermek için [kullanıcı profilindeki bu niteliği kontrol edin](subscription-status). Erişimi güncellemek için kontrol panelindeki niteliği değiştirmeniz yeterlidir. ::: ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: CUSTOMER_USER_ID' \ --data '{ "access_level_id": "YOUR_ACCESS_LEVEL" }' ``` ## Adım 3. Uygulamada erişimi doğrulayın \{#step-3-verify-access-in-the-app\} API aracılığıyla erişim verildikten sonra kullanıcının profili otomatik olarak güncellenir. Abonelik durumunu kontrol etmek ve premium özelliklerin kilidini açmak için profilini çekin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL_ID") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL_ID").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL_ID"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: web-api --- --- title: Adapty Web API description: "" --- Web API, web uygulamalarında kullanılmak üzere tasarlanmış sunucu taraflı API'nin bir uzantısıdır. İlgili placement ID'si aracılığıyla doğru paywall'u almanızı ve doğru dönüşüm takibi için paywall görüntülemelerini kaydetmenizi sağlar. Bu sayede Adapty'deki A/B testlerinden ve paywall kişiselleştirmesinden yararlanabilir, hangi paywall'ların en iyi performansı gösterdiğini takip edebilirsiniz. ## Kullanım senaryosu: Web uygulamanızdan bir işlemi kaydedin ve kullanılan paywall ile ilişkilendirin \{#use-case-record-a-transaction-from-your-web-app-and-link-it-to-the-used-paywall\} Diyelim ki web uygulamanızda ürün satıyorsunuz. Kullanıcılarınıza bir paywall göstermeniz, onların bir ürün satın almasına izin vermeniz ve ardından işlem ayrıntılarını Adapty'ye eklemeniz gerekiyor. Bu işlemleri, kullanıcının satın almayı gerçekleştirdiği belirli paywall'larla ilişkilendirmek, analizlerinizin doğru verileri yansıtması açısından kritik önem taşır. Bunu Adapty API kullanarak kolayca yapabilirsiniz. ### Ön koşullar \{#prerequisites\} 1. Adapty Kontrol Paneli'nde paywall'da kullanacağınız [ürünleri oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [paywall oluşturun](create-paywall). Web paywall'unuzu tasarlamak için [remote config kullanın](customize-paywall-with-remote-config). 3. Adapty Kontrol Paneli'nde bir [placement oluşturun](create-placement) ve paywall'u bu placement ile ilişkilendirin. ### Adapty API ile adımlar \{#steps-with-adapty-api\} 1. **Kullanıcı profili oluşturun:** Adapty, paywall isteğinde bulunmadan önce bir profile ihtiyaç duyar; bu sayede sonucu isteği yapan kullanıcıya göre kişiselleştirebilir. Kullanıcı profili oluşturmak için [Profil oluştur](api-adapty/operations/createProfile) isteğini kullanın. 2. **Paywall'u alın ve görüntüleyin:** Kullanıcı web uygulamanızda paywall'un gösterilmesi gereken placement'a ulaştığında, [placement ID](placements) üzerinden paywall'u almak için [Paywall al](api-web/operations/getPaywall) isteğini kullanın. Sonuç olarak, kullanıcınıza karşılık gelen [kitle](audience) için bir paywall alırsınız. Döndürülen ürünleri ve (isteğe bağlı olarak) bu paywall'un [remote config](customize-paywall-with-remote-config)'ini kullanarak paywall'u kendi kodunuzla görüntüleyin. 3. **Paywall görüntülemesini kaydedin:** Analizlerinizin bu olayı doğru şekilde yansıtması için [Paywall görüntülemesini kaydet](api-web/operations/recordPaywallView) isteğini kullanarak paywall görüntülemesini Adapty'ye kaydedin. Bu, dönüşümleri doğru takip etmek açısından hayati önem taşır. 4. **Satın almayı kaydedin:** Kullanıcı bir satın alma işlemi tamamlarsa, işlem ayrıntılarını Adapty API aracılığıyla Adapty'ye gönderin. İşlemi gösterilen belirli paywall ile ilişkilendirmek için bu isteğe **variation ID**'yi ekleyin. Rehberlik için [mobil uygulamalarda paywall'ları işlemlerle ilişkilendirme](report-transactions-observer-mode) sayfamıza göz atın; aynı yaklaşım web uygulamaları için de geçerlidir. 5. **Pazarlama attribution verisi ekleyin (gerekiyorsa):** Herhangi bir pazarlama attribution veriniz varsa (ör. kampanya veya reklam ayrıntıları), analizleri zenginleştirmek ve Adapty'deki reklam performansınız hakkında daha fazla bilgi edinmek için [Attribution ekle](api-web/operations/addAttribution) isteğini kullanarak bu veriyi kullanıcı profiline ekleyin. --- **Sırada ne var:** - [Web API yetkilendirmesi](web-api-authorization) ile devam edin - İstekler: - [Attribution ekle](api-web/operations/addAttribution) - [Paywall al](api-web/operations/getPaywall) - [Paywall görüntülemesini kaydet](api-web/operations/recordPaywallView) --- # File: web-api-authorization --- --- title: Web API için Yetkilendirme ve İstek Formatı description: "" --- ## Yetkilendirme \{#authorization\} API istekleri, **Authorization** başlığına `Api-Key {your_public_api_key}` değeri verilerek kimlik doğrulaması yapılmalıdır; örneğin `Api-Key public_live_...`. Bu anahtarı [Adapty Kontrol Paneli -> **App Settings** -> **General** sekmesi -> **API keys** bölümü](https://app.adapty.io/settings/general) içinde bulabilirsiniz. :::important API anahtarları uygulamaya özgüdür. Birden fazla uygulamanız varsa her biri için farklı anahtar kullandığınızdan emin olun. ::: ## İstek formatı \{#request-format\} - **Content-Type başlığı**: API'nin isteğinizi işleyebilmesi için **Content-Type** başlığını `application/json` olarak ayarlayın. - **Gövde**: API, isteğin gövdesinin JSON formatında olmasını bekler. --- # File: web-api-requests --- --- title: "Web API İstekleri" description: "" --- Adapty'nin sunucu taraflı API'si, abonelik verilerinize programatik olarak erişip yönetmenizi sağlar; böylece mevcut servisleriniz ve altyapınızla sorunsuz entegrasyon kurabilirsiniz. Platformlar arası veri senkronizasyonu, access level tanımlama veya Stripe'ta satın alma doğrulama gibi işlemlerde bu API, sistemlerinizi senkronize tutmak ve kullanıcılarınızı aktif kılmak için ihtiyacınız olan araçları sunar. ## Postman koleksiyonu ve ortamı \{#postman-collection-and-environment\} Web API'yi daha kolay kullanabilmeniz için Postman'a indirip aktarabileceğiniz bir koleksiyon ve ortam dosyası hazırladık. - **İstek Koleksiyonu**: Adapty web API'sinde mevcut tüm istekleri içerir. Ortamda tanımlayabileceğiniz değişkenler kullandığını unutmayın. - **Ortam**: Değerleri bir kez tanımlayabileceğiniz değişkenlerin listesini içerir. Sunucu taraflı API, web API ve analytics export API için birleşik bir ortam hazırladık. Bu ortamı aktif hale getirdikten sonra Postman, tanımlanan değişken değerlerini isteklerinizde otomatik olarak kullanır. :::tip [Koleksiyonu ve ortamı indirin](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_Web_API_postman_collection.zip) ::: Bir koleksiyonu ve ortamı Postman'a nasıl aktaracağınız hakkında bilgi almak için lütfen [Postman belgelerine](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/) başvurun. ## Kullanılan değişkenler \{#variables-used\} İş akışınızı kolaylaştırmak için sunucu taraflı API, web API ve analytics export API için birleşik bir ortam oluşturduk. Aşağıda web API'sine özgü değişkenler yer almaktadır: | Değişken | Açıklama | Örnek Değer | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | public_api_key | [**App settings**](https://app.adapty.io/settings/general) sayfasındaki **Public SDK key** alanında bulabilirsiniz. | `public_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | | adapty-customer-user-id | Sisteminizde kullandığınız kullanıcı ID'si. Adapty Kontrol Paneli'nde Profil'in **Customer user ID** alanında bulabilirsiniz. | `john.doe@example.com` | | adapty-profile-id | Adapty tarafından atanan kullanıcı ID'si. Adapty Kontrol Paneli'nde Profil'in **Adapty ID** alanında bulabilirsiniz. | `3286abd3-48b0-4e9c-a5f6-ac0a006333a6` | **Sırada ne var: İstekler:** - [Paywall getir](api-web/operations/getPaywall) - [Paywall görüntüleme kaydet](api-web/operations/recordPaywallView) - [Attribution ekle](api-web/operations/addAttribution) --- # File: export-analytics-api --- --- title: API ile analitik dışa aktarma --- Analitik verilerinizi CSV olarak dışa aktarmak, uygulamanızın performans metriklerini daha ayrıntılı incelemenize, raporları özelleştirmenize ve zaman içindeki eğilimleri analiz etmenize olanak tanır. Adapty API ile detaylı analitik verileri kolayca CSV formatına çekebilir; bu sayede verilerinizi takip etmek, paylaşmak ve içgörülerinizi geliştirmek çok daha pratik hale gelir. :::tip Analitik verilerini çekmek için bir AI ajan veya LLM kullanıyor musunuz? [Analitik verilerinizi AI ajan ile dışa aktarın](export-analytics-with-ai) başlıklı makaleye göz atın. ::: ## Analitik dışa aktarma API'sine başlarken \{#getting-started-with-the-api-for-analytics-export\} Analitik dışa aktarma API'si ile örneğin şunları yapabilirsiniz: 1. **Pazarlama Kampanyalarından MRR Analizi**: Belirli bir ülkedeki geçen yılın pazarlama kampanyalarının etkisini ölçerek hangilerinin en yüksek geliri getirdiğini haftalık takiple görün. Bunun için [Analitik verilerini al](api-export-analytics/operations/retrieveAnalyticsData) yöntemini kullanın. 2. **Kohort Tutundurmasını Zaman İçinde Takip Edin**: Düşüş noktalarını tespit etmek ve kohortları zaman içinde karşılaştırmak için kohort bazında tutundurma oranını takip edin; bu sayede etkileşim stratejilerinin tutundurma üzerindeki kritik anlara ilişkin trendleri ortaya çıkarabilirsiniz. Belirli bir uygulama mağazasıyla, belirli bir ülkeyle ve belirli bir ürünle sınırlıdır. Bunun için [Kohort verilerini getir](api-export-analytics/operations/retrieveCohortData) yöntemini kullanın. 3. **Dönüşüm Oranlarını Kanallara Göre Değerlendirin**: Hangi edinme kanallarının ilk satın almayı en etkili şekilde yönlendirdiğini görmek için temel kanalların dönüşüm oranlarını analiz edin. Bu, pazarlama harcamalarını yüksek performanslı kanallara yönlendirmenize yardımcı olur. Bunun için [Dönüşüm verilerini al](api-export-analytics/operations/retrieveConversionData) yöntemini kullanın. 4. **Churn Rate'i İnceleyin**: Kullanıcıların ne kadar hızlı aboneliğini iptal ettiğini izleyerek churn örüntülerini keşfedin ya da belirli bir ülke ve belirli bir ürün odaklı olarak elde tutma çalışmalarınızın başarısını ölçün. Bunun için [Huni verilerini getir](api-export-analytics/operations/retrieveFunnelData) metodunu kullanın. 5. **Kullanıcı Segmentine Göre LTV'yi Değerlendirin**: Zaman içinde en yüksek geliri hangi grupların getirdiğini anlamak için farklı kullanıcı segmentlerinin yaşam boyu değerini belirleyin. Uzun vadeli aboneler gibi yüksek değerli segmentlere odaklanın ve sonuçları edinim stratejilerini iyileştirmek için kullanın. Bunun için [LTV verilerini al](api-export-analytics/operations/retrieveLTVData) yöntemini kullanın. 6. **Ülkeye Göre Elde Tutmayı Kontrol Edin**: Yüksek etkileşimli pazarları bulmak ve yerelleştirme veya bölgesel stratejilere yön vermek için bölgeye göre elde tutma oranlarına bakın. Bunun için [Elde tutma verilerini al](api-export-analytics/operations/retrieveRetentionData) metodunu kullanın. --- **Sırada ne var**: - [Yetkilendirme ve istek formatı](export-analytics-api-authorization) - [Analitik API isteklerini dışa aktarma](export-analytics-api-requests) --- # File: export-analytics-api-authorization --- --- title: Analitik API'yi Dışa Aktarma için Yetkilendirme ve İstek Formatı --- ## Yetkilendirme \{#authorization\} API isteklerinizi, `Authorization` başlığında gizli API anahtarınızla kimlik doğrulamanız gerekir. Bu anahtarı [App Settings](https://app.adapty.io/settings/general) sayfasında bulabilirsiniz. Format şu şekildedir: `Api-Key {YOUR_SECRET_API_KEY}`, örneğin: `Api-Key secret_live_...`. :::important API anahtarları uygulamaya özeldir. Birden fazla uygulamanız varsa her biri için farklı anahtarlar kullandığınızdan emin olun. ::: ## İstek formatı \{#request-format\} **Başlıklar** Sunucu tarafı API istekleri, belirli başlıklar ve bir JSON gövdesi gerektirir. İsteklerinizi yapılandırmak için aşağıdaki ayrıntıları kullanın: | Başlık | Açıklama | | ------------ | ------------------------------------------------------------ | | Content-Type | (Zorunlu) API'nin isteği işleyebilmesi için `application/json` olarak ayarlayın. | | Adapty-Tz | (İsteğe bağlı) Verilerin nasıl gruplandırılacağını ve görüntüleneceğini tanımlamak için saat dilimini ayarlayın. [IANA Saat Dilimi Veritabanı formatını](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) kullanın (ör. `Europe/Berlin`). | ## Gövde \{#body\} API, istek için gerekli verileri içeren JSON formatında bir gövde bekler. ## Hız sınırları \{#rate-limits\} API anahtarı başına saniyede maksimum 2 istek gönderilebilir. Bu sınırı aşmanız durumunda `429 Too Many Requests` hatası döner. ## API anahtarlarını yenileme \{#rotate-api-keys\} Gizli API anahtarlarını yenilemek için: 1. **Settings → General** sayfasında **Generate new key** butonuna tıklayın, ardından eski anahtarın yanındaki çöp kutusu simgesine tıklayın. 2. Uygulamanızda kullanılan anahtarı güncelleyin. --- **Sırada ne var: İstekler:** - [Analitik verilerini al](api-export-analytics/operations/retrieveAnalyticsData) - [Kohort verilerini al](api-export-analytics/operations/retrieveCohortData) - [Dönüşüm verilerini al](api-export-analytics/operations/retrieveConversionData) - [Huni verilerini al](api-export-analytics/operations/retrieveFunnelData) - [Yaşam Boyu Değer (LTV) verilerini al](api-export-analytics/operations/retrieveLTVData) - [Elde tutma verilerini al](api-export-analytics/operations/retrieveRetentionData) --- # File: export-analytics-api-requests --- --- title: Analytics API isteklerini dışa aktarma --- Analytics verilerinizi CSV olarak dışa aktarmak, uygulamanızın performans metriklerini daha derinlemesine incelemenizi, özel raporlar oluşturmanızı ve zaman içindeki eğilimleri analiz etmenizi sağlar. Adapty API ile ayrıntılı analytics verilerini kolayca CSV formatına çekebilir; böylece verilerinizi istediğiniz zaman takip edebilir, paylaşabilir ve analiz edebilirsiniz. ## Postman koleksiyonu ve ortamı \{#postman-collection-and-environment\} Analytics verilerini dışa aktarmak için API'yi kullanımı kolaylaştırmak amacıyla, Postman'e indirip içe aktarabileceğiniz bir Postman koleksiyonu ve ortam dosyası hazırladık. - **İstek Koleksiyonu**: Adapty analytics dışa aktarma API'sinde mevcut tüm istekleri içerir. Ortamda tanımlayabileceğiniz değişkenler kullandığını unutmayın. - **Ortam**: Değerleri bir kez tanımlayabileceğiniz değişkenlerin listesini içerir. Sunucu tarafı API, web API ve analytics dışa aktarma API'si için birleşik bir ortam hazırladık. Bu ortamı etkin hale getirdikten sonra Postman, isteklerinizdeki değişken değerlerini otomatik olarak yerine koyar. :::tip [Koleksiyon ve ortamı indirin](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_export_analytics_API_postman_collection.zip) ::: Bir koleksiyonu ve ortamı Postman'e nasıl içe aktaracağınız hakkında bilgi için lütfen [Postman belgelerine](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/) başvurun. ### Kullanılan değişkenler \{#variables-used\} İş akışınızı kolaylaştırmak amacıyla sunucu tarafı API, web API ve analytics dışa aktarma API'si için birleşik bir ortam oluşturduk. Aşağıda analytics dışa aktarma API'sine özgü değişkenler yer almaktadır: | Değişken | Açıklama | Örnek Değer | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | secret_api_key | [**App settings**](https://app.adapty.io/settings/general) sayfasındaki **Secret key** alanında bulabilirsiniz. | `secret_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | **İstekler:** - [Analytics verilerini getir](api-export-analytics/operations/retrieveAnalyticsData) - [Kohort verilerini getir](api-export-analytics/operations/retrieveCohortData) - [Dönüşüm verilerini getir](api-export-analytics/operations/retrieveConversionData) - [Huni verilerini getir](api-export-analytics/operations/retrieveFunnelData) - [Yaşam Boyu Değer (LTV) verilerini getir](api-export-analytics/operations/retrieveLTVData) - [Elde tutma verilerini getir](api-export-analytics/operations/retrieveRetentionData) --- # End of Documentation _Generated on: 2026-07-24T13:02:34.253Z_ _Successfully processed: 17/18 files_ # CAPACITOR - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.254Z Total files: 45 --- # File: capacitor-sdk-overview --- --- title: "Capacitor SDK'ya genel bakış" description: "Adapty Capacitor SDK ve temel özellikleri hakkında bilgi edinin." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Hoş geldiniz! Uygulama içi satın almaları kolaylaştırmak için buradayız 🚀 [Adapty Capacitor SDK](https://github.com/adaptyteam/AdaptySDK-Capacitor/)'yi, uygulama içi satın alma sürecinin karmaşıklığını üstlenerek sizi asıl işinize — harika uygulamalar geliştirmeye — odaklanmanız için oluşturduk. İşte sizin adınıza halledeceğimiz şeyler: - Satın alma işlemleri, makbuz doğrulama ve abonelik yönetimini kutudan çıkar çıkmaz kullanın - Uygulama güncellemesi gerektirmeden paywall oluşturun ve test edin - Sıfır kurulumla ayrıntılı satın alma analizleri alın — kohort, LTV, churn ve dönüşüm hunisi analizi dahil - Kullanıcı abonelik durumunu oturumlar ve cihazlar genelinde her zaman güncel tutun - Uygulamanızı yalnızca tek satır kodla pazarlama attribution ve analitik hizmetleriyle entegre edin :::note Koda dalmadan önce Adapty'yi App Store Connect ve Google Play Console ile entegre etmeniz, ardından kontrol panelinde ürünleri ayarlamanız gerekecek. Her şeyi önce yapılandırmak için [hızlı başlangıç kılavuzumuza](quickstart) göz atın. ::: ## Başlarken \{#get-started\} For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. Entegrasyon kılavuzunda şunları ele alacağız: 1. [SDK'yı yükle ve yapılandır](sdk-installation-capacitor): SDK'yı projenize bir [bağımlılık](https://www.npmjs.com/package/@adapty/capacitor) olarak ekleyin ve kodda etkinleştirin. 2. [Paywall'lar aracılığıyla satın almaları etkinleştir](capacitor-quickstart-paywalls): Kullanıcıların ürün satın alabilmesi için satın alma akışını ayarlayın. 3. [Abonelik durumunu kontrol et](capacitor-check-subscription-status): Kullanıcının abonelik durumunu otomatik olarak kontrol edin ve ücretli içeriklere erişimlerini yönetin. 4. [Kullanıcıları tanımla (isteğe bağlı)](capacitor-quickstart-identify): Kullanıcıları Adapty profilleriyle ilişkilendirerek verilerinin cihazlar arasında tutarlı biçimde saklanmasını sağlayın. ### Nasıl çalıştığını görün \{#see-it-in-action\} Her şeyin nasıl bir araya geldiğini görmek ister misiniz? Sizi düşündük: **Örnek uygulamalar**: Tam kurulumu gösteren kapsamlı örneklere göz atın: - [React](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-react-example) - [Vue.js](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-vue-example) - [Angular](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-angular-example) - [Gelişmiş geliştirici araçları](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools) ## Temel kavramlar \{#main-concepts\} Koda dalmadan önce Adapty'yi çalıştıran temel kavramları tanıyalım. Adapty'nin yaklaşımının güzelliği şudur: uygulamanızda yalnızca placement'lar sabit kodlanır. Diğer her şey — ürünler, paywall tasarımları, fiyatlandırma ve teklifler — uygulama güncellemesi gerektirmeden Adapty kontrol panelinden esnek biçimde yönetilebilir: 1. **Ürün** - Uygulamanızda satın alınabilecek her şey — abonelik, consumable ürün veya süresiz erişim. 2. **Flow veya paywall** - Bir placement'a bağlı, konfigürasyonla birleştirilmiş ürünler. İki türü vardır: - **[Flow](adapty-flow-builder)** - Flow Builder'da oluşturulmuş görsel, kodsuz arayüz. Adapty, kullanıcı arayüzünü render eder ve satın alma işlemini sizin adınıza yönetir. - **[Paywall](paywalls)** - Görsel konfigürasyon yoktur; kullanıcı arayüzünü kendi kodunuzda siz oluşturur ve `makePurchase`'ı kendiniz çağırırsınız. Bkz. [Paywall'ları manuel olarak uygulama](capacitor-quickstart-manual). SDK kodunda her ikisi de aynı `getFlow` metodu aracılığıyla alınır. 3. **Placement** - Kullanıcı yolculuğunuzda bir paywall göstermek istediğiniz stratejik nokta. Placement'ları monetizasyon stratejinizin "nerede" ve "ne zaman"ı olarak düşünebilirsiniz. Yaygın placement'lar şunlardır: - `main` - Ana paywall konumunuz - `onboarding` - Kullanıcı onboarding flow'u sırasında gösterilir - `settings` - Uygulamanızın ayarlarından erişilebilir İlk entegrasyon için `main` veya `onboarding` gibi temellerle başlayın, ardından uygulamanızda kullanıcıların satın almaya hazır olabileceği başka yerleri düşünün. 4. **Profil** - Kullanıcılar bir ürün satın aldığında, profillerine ücretli özelliklere erişimi tanımlamak için kullandığınız bir **access level** atanır. --- # File: sdk-installation-capacitor --- --- title: "Capacitor - Adapty SDK kurulumu ve yapılandırması" description: "Abonelik tabanlı uygulamalar için Capacitor'da Adapty SDK kurulumuna ilişkin adım adım kılavuz." --- Adapty SDK, Capacitor uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu modül, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: Bu modül, kolayca çapraz platform paywall'lar oluşturmak için kullanılan, kullanıcı dostu ve kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. AdaptyUI, core modülle birlikte otomatik olarak etkinleştirilir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywall gösterme, satın alma yapma ve diğer temel işlevler dahil tam kurulumu gösteren [örnek uygulamalarımıza](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples) göz atın. ::: ## Gereksinimler \{#requirements\} [Adapty Capacitor SDK](https://github.com/adaptyteam/AdaptySDK-Capacitor/) aşağıdaki sürüm gereksinimlerine sahiptir: | Adapty SDK Sürümü | Capacitor Sürümü | iOS Sürümü | |--------------------|-------------------|-------------| | 3.16.0+ | 8 | 15.0+ | | 3.15 | 7 | 14.0+ | Capacitor 6 ve altı sürümler desteklenmemektedir. Adapty SDK v4 (beta) ile iOS için geliştirme yapmak **Xcode 26** veya daha yeni bir sürüm gerektirir — kullandığı yerel iOS SDK'sı Swift tools 6.2 ile oluşturulmuştur. iOS 15.0+, Capacitor 8 ve Android minSdk 24 gereksinimleri SDK 3.16+ ile aynıdır. :::info SDK v3.17'den itibaren Adapty SDK, varsayılan olarak Google Play Billing Library v8.0.0 kullanmaktadır. ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} :::important Aşağıdaki adımlar Adapty SDK 3.x'i yükler. [Flow Builder](adapty-flow-builder) için gerekli olan ve [hızlı başlangıç](capacitor-quickstart-paywalls) tarafından kullanılan SDK v4 (beta) farklı şekilde yüklenir: aşağıdaki [Adapty SDK 4.0 (beta)](#adapty-sdk-40-beta) bölümünü izleyin ya da [geçiş kılavuzuna](migration-to-capacitor-sdk-v4) bakın. ::: [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Adapty SDK'yı yükleyin: ```sh npm install @adapty/capacitor npx cap sync ``` ### Adapty SDK 4.0 (beta) Capacitor SDK 4.0 — [Flow Builder](adapty-flow-builder) desteği ekleyen bu sürüm — bir ön sürümdür. Tam sürümü belirterek yükleyin (npm, caret/tilde aralıklarıyla ön sürümleri çözemez), ardından sync yapın: ```sh npm install @adapty/capacitor@4.0.0-beta.2 ``` ```sh npx cap sync ``` iOS'ta v4, yerel Adapty SDK'larını yalnızca **Swift Package Manager** üzerinden çeker — CocoaPods podspec kaldırıldı ([CocoaPods'un spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). Uygulamanızın iOS projesinin Capacitor'ın SPM entegrasyonunu kullanması gerekir: - Yeni uygulamalar için, iOS platformunu SPM paket yöneticisiyle ekleyin: ```sh npx cap add ios --packagemanager SPM ``` - Mevcut uygulamalar için, iOS projesini CocoaPods'tan SPM'e taşımak üzere [Capacitor'ın mevcut bir projede SPM kullanma kılavuzunu](https://capacitorjs.com/docs/ios/spm#using-spm-in-an-existing-capacitor-project) takip edin. v4'teki API değişikliklerinin tam listesi için bkz. [Adapty Capacitor SDK'sını v4'e Taşıma](migration-to-capacitor-sdk-v4). ## Adapty SDK'nın Adapty modülünü etkinleştirin \{#activate-adapty-module-of-adapty-sdk\} :::note Adapty SDK'nın uygulamanızda yalnızca bir kez etkinleştirilmesi yeterlidir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. Adapty'yi etkinleştirmek için aşağıdaki kodu herhangi bir uygulama dosyasına kopyalayın: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // verbose logging is recommended for the development purposes and for the first production release logLevel: 'verbose', // in the development environment, use this variable to avoid multiple activation errors. Set it to your development environment variable __ignoreActivationOnFastRefresh: true, } }); console.log('Adapty activated successfully!'); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `activate` metodunun tamamlanmasını bekleyin. Tam sıralama için [Capacitor SDK'da çağrı sırası](capacitor-sdk-call-order) bölümüne bakın. ::: :::tip Geliştirme ortamında aktivasyon hatalarından kaçınmak için [ipuçlarını](#development-environment-tips) kullanın. ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız [Paywall Builder hızlı başlangıç kılavuzunu](capacitor-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız [özel paywalllar için hızlı başlangıç kılavuzuna](capacitor-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız AdaptyUI modülüne ihtiyacınız var. Core modülü etkinleştirdiğinizde bu otomatik olarak yapılır; başka bir şey yapmanıza gerek yoktur. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlükleme \{#logging\} #### Günlük sistemini yapılandırın \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri günlüğe kaydeder. Aşağıdaki seviyeler kullanılabilir: | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Yalnızca hatalar loglanır | | `warn` | Kritik hatalara yol açmayan ancak dikkat edilmesi gereken hatalar ve SDK mesajları loglanır | | `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır | | `verbose` | Hata ayıklama sırasında işe yarayabilecek her türlü ek bilgi (fonksiyon çağrıları, API sorguları vb.) loglanır | Adapty yapılandırmasından önce veya yapılandırma sırasında uygulamanızda log seviyesini ayarlayabilirsiniz: ```typescript showLineNumbers // Set log level before activation adapty.setLogLevel({ logLevel: 'verbose' }); // Or set it during configuration await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { logLevel: 'verbose', } }); ``` ### Veri politikaları \{#data-policies\} Adapty, kullanıcılarınızın kişisel verilerini siz açıkça göndermediğiniz sürece saklamaz; ancak mağaza veya ülke yönergelerine uymak için ek veri güvenlik politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşımını devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi, kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özellikler uygulamanız için gerekli değilse gereksiz veri toplamayı azaltmak amacıyla kullanabilirsiniz. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ipAddressCollectionDisabled: true, } }); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `ios.idfaCollectionDisabled` (iOS) veya `android.adIdCollectionDisabled` (Android) değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; App Store/Play Store politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak veya uygulamanız reklam kimliklerine dayalı attribution ya da analitik gerektirmiyorsa kullanın. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, } }); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) varsayılan olarak önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. Varsayılan önbellek ayarlarını geçersiz kılmak için `mediaCache` kullanın: ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, } }); ``` | Parametre | Zorunlu | Açıklama | |-----------|---------|----------| | memoryStorageTotalCostLimit | isteğe bağlı | Bellekteki toplam önbellek boyutu (bayt cinsinden). Platform'a özgü varsayılan değer kullanılır. | | memoryStorageCountLimit | isteğe bağlı | Bellek deposundaki öğe sayısı sınırı. Platform'a özgü varsayılan değer kullanılır. | | diskStorageSizeLimit | isteğe bağlı | Diskteki dosya boyutu sınırı (bayt cinsinden). Platform'a özgü varsayılan değer kullanılır. | ### Yerel access level'ları etkinleştirin (Android) \{#enable-local-access-levels-android\} Varsayılan olarak [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `localAccessLevelAllowed` değerini `true` olarak ayarlayın: ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { localAccessLevelAllowed: true, }, } }); ``` ### Yedekten geri yüklemede veriyi temizleme \{#clear-data-on-backup-restore\} `clearDataOnBackup` `true` olarak ayarlandığında, SDK uygulamanın iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywaller dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. Ardından SDK temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple'daki işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { clearDataOnBackup: true, }, } }); ``` ## Geliştirme ortamı ipuçları \{#development-environment-tips\} #### Capacitor'ın canlı yenileme özelliğinde SDK etkinleştirme hatalarını giderme \{#troubleshoot-sdk-activation-errors-on-capacitors-live-reload\} Capacitor'da Adapty SDK ile geliştirme yaparken şu hatayla karşılaşabilirsiniz: `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` Bu hata, Capacitor'ın canlı yenileme özelliğinin geliştirme sırasında birden fazla etkinleştirme çağrısını tetiklemesinden kaynaklanır. Bunu önlemek için `__ignoreActivationOnFastRefresh` seçeneğini Capacitor'ın geliştirme modu bayrağına ayarlayın; kullandığınız pakete göre bu bayrak farklılık gösterebilir. ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // Set your development environment variable __ignoreActivationOnFastRefresh: true, } }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` ## Sorun Giderme \{#troubleshooting\} #### Minimum iOS sürüm hatası \{#minimum-ios-version-error\} :::note Bu, **SDK 3.x** kullanan CocoaPods tabanlı projeler için geçerlidir. SDK 4.0, iOS'a Swift Package Manager üzerinden kurulur (`Podfile` yoktur) ve iOS 15.0 gerektirir — Xcode'da deployment target'ı 15.0 olarak ayarlayın. ::: SDK 3.x'te minimum iOS sürüm hatası alıyorsanız Podfile'ınızı güncelleyin: ```diff -platform :ios, min_ios_version_supported +platform :ios, '15.0' ``` #### Android yedekleme kuralları (Otomatik Yedekleme yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::tip Yerel Android dosyalarını değiştirdikten sonra, platformu yeniden oluşturursanız Capacitor'ın güncellenmiş kaynakları alması için `npx cap sync android` komutunu çalıştırın. ::: #### Android'de başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} Satın alma akışını başlatan Activity, varsayılan olmayan bir `launchMode` kullanıyorsa Android, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan döndüğünde bu Activity'yi yanlış şekilde yeniden oluşturabilir veya yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına ya da iptal edilmiş olarak değerlendirilmesine yol açabilir. Satın alma işlemlerinin doğru çalışması için, satın alma akışını başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın; diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma akışını başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile SWIFT_VERSION geçersiz kılmasından kaynaklanan Swift 6 derleme hataları \{#swift-6-build-errors-caused-by-podfile-swift-version-override\} :::note Bu, **SDK 3.x** kullanan CocoaPods tabanlı projeler için geçerlidir. SDK 4.0, native SDK'ları Swift Package Manager üzerinden kurduğu için ayarlanacak bir `Podfile` bulunmaz. ::: Capacitor uygulamanızı iOS için derlerken Adapty pod hedeflerinde Swift 6 derleme hatalarıyla karşılaşabilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içinde `@Sendable` uyumsuzlukları, Adapty türlerinde eksik `Sendable` uyumu veya aktör izolasyon hataları sayılabilir. Adapty pod'ları `s.swift_version = '6.0'` olarak tanımlıdır ve derleme için Swift 6 gerektirir. Kendi uygulama kodunuz Swift 5'te kalabilir — yalnızca Adapty pod hedeflerinin (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`, `AdaptyLogger`, `AdaptyPlugin`) Swift 6 ile derlenmesi gerekir. En yaygın neden, `ios/App/Podfile` dosyasındaki her pod hedefi için `SWIFT_VERSION` değerini yeniden yazan bir `post_install` hook'udur: ```ruby showLineNumbers title="ios/App/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **Düzeltme**: Adapty pod hedeflerini bu geçersiz kılmanın dışında tutun: ```ruby showLineNumbers title="ios/App/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` Ardından `npx cap sync ios` komutunu çalıştırın ve yeniden derleyin. Doğrulamak için `ios/App/Pods/Pods.xcodeproj` dosyasını açın, `Adapty` pod hedefini seçin → **Build Settings** → **Swift Language Version**. Değerin **Swift 6** olması gerekir. --- # File: capacitor-quickstart-paywalls --- --- title: "Capacitor SDK ile Flow Builder kullanarak satın almaları etkinleştirme" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmek için hızlı başlangıç kılavuzu." --- Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – no-code Flow Builder ile oluşturulan, kullanıcılara ürünleri sunan ekran dizileri. SDK bunları `getFlow` aracılığıyla getirir. Kullanıcı arayüzünü kendi kodunuzla oluşturmayı tercih ediyorsanız bunun yerine bir paywall kullanın — bkz. [Paywalleri manuel olarak uygulama](capacitor-quickstart-manual). - [**Placement'lar**](placements) – uygulamanızda flow'ları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde flow'ları placement'lara bağlar, ardından kodunuzda placement ID'si ile bunları talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın almaları etkinleştirmek için üç farklı yöntem sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne Zaman Kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm karmaşık satın alma akışını, makbuz doğrulamayı ve abonelik yönetimini arka planda halleder. | | Manuel oluşturulan paywall'lar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız, ancak ürün tekliflerinde esnekliği korumak için flow nesnesini Adapty'den alırsınız. [Kılavuza](capacitor-quickstart-manual) bakın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı sınırlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl uygulanacağını göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ederseniz, bkz. [Paywall'ları manuel olarak uygulama](capacitor-quickstart-manual). ::: Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Gösterin ve satın alma işlemlerini Adapty yönetsin**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın tepkileriyle ilişkilendirin. Örneğin, kullanıcılar butona tıkladığında bağlantıları açın veya flow'u kapatın. ## Başlamadan Önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Uygulamanızı Adapty Kontrol Paneli'nde [App Store](initial_ios) ve/veya [Google Play](initial-android) ile bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ürünleri ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'unuzu ekleyin](create-placement). 5. Uygulama kodunuzda [Adapty SDK'yı kurun ve etkinleştirin](sdk-installation-capacitor). Bu kılavuz Adapty Capacitor SDK v4 API'larını kullanmaktadır. ## 1. Flow'u alın \{#1-get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturulmuş bir flow'u almak için `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın. Flow, görüntülenmek için gereken UI öğelerini ve stil bilgilerini içerir. ```typescript showLineNumbers title="Capacitor" try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested flow } catch (error) { // handle the error } ``` ## 2. Flow'u görüntüleyin \{#display-the-flow\} Flow'a sahip olduğunuzda, onu görüntülemek için yalnızca birkaç satır eklemeniz yeterli. `createFlowView` metoduyla bir `view` oluşturun, olay işleyicilerini ayarlayın, ardından `view.present()` çağrısını yapın. Her `view` yalnızca bir kez kullanılabilir. Flow'u tekrar görüntülemeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createFlowView`'ı bir kez daha çağırın. ```typescript showLineNumbers title="Capacitor" try { const view = await createFlowView(flow); await view.setEventHandlers({ onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type === 'success'; // close the flow on a successful purchase, keep it open for cancelled or pending purchases }, }); await view.present(); } catch (error) { // handle the error } ``` :::tip Bir flow'un nasıl görüntüleneceğine dair daha fazla ayrıntı için [kılavuzumuza](capacitor-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#handle-button-actions\} Kullanıcılar flow'daki butonlara tıkladığında, Capacitor SDK satın alma, geri yükleme, flow'u kapatma ve URL açma işlemlerini otomatik olarak gerçekleştirir. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve bu eylemlerin kodunuzda yönetilmesi gerekir. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, kapatma butonu için varsayılan davranış aşağıdaki gibidir. Bunu koda eklemeniz gerekmez, ancak gerektiğinde nasıl yapıldığını buradan görebilirsiniz. ```typescript showLineNumbers title="Capacitor" const unsubscribe = await view.setEventHandlers({ onCloseButtonPress() { return true; // allow the flow to close }, }); ``` :::tip Düğme [eylemlerini](capacitor-handle-paywall-actions) ve [olayları](capacitor-handling-events) nasıl yöneteceğiniz hakkındaki kılavuzlarımızı okuyun. ::: ## Sonraki adımlar :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Flow'unuz uygulamada görüntülenmeye hazır. Flow üzerinden test satın alma işlemini tamamlayabildiğinizden emin olmak için [satın almalarınızı test edin](capacitor-test). Şimdi, flow'u veya ücretli özelliklere erişimi doğru kullanıcılara sunduğunuzdan emin olmak için [kullanıcıların access level durumunu kontrol etmeniz](capacitor-check-subscription-status) gerekiyor. ## Tam örnek \{#full-example\} Bu kılavuzdaki tüm adımlar uygulamanıza şu şekilde entegre edilebilir. ```typescript showLineNumbers title="Capacitor" export async function showFlow() { try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', }); const view = await createFlowView(flow); await view.setEventHandlers({ onCloseButtonPress() { return true; }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type === 'success'; // close the flow on a successful purchase, keep it open for cancelled or pending purchases }, }); await view.present(); } catch (error) { // handle any error that may occur during the process console.warn('Error showing flow:', error); } } ``` --- # File: capacitor-check-subscription-status --- --- title: "Capacitor SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Capacitor uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) bilgisini kontrol etmeniz gerekir. Bu makale, kullanıcılara paywall gösterip göstermeyeceğinize ya da ücretli özelliklere erişim izni verip vermeyeceğinize karar vermek için profil durumuna nasıl ulaşacağınızı anlatmaktadır. ## Abonelik durumunu alma \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profildeki [access level](access-level) bilgisini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verisine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) ya da güncellemeyi zorla almak istediğinizde `getProfile` çağırın. - Abonelik durumu her değiştiğinde otomatik olarak güncellenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** ayarlayın. ### Profili alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek amacıyla `adapty.addListener('onLatestProfileLoad')` kullanın. Adapty, kullanıcının abonelik durumu her değiştiğinde bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncellenmiş profil verisini saklayın; böylece uygulamanızın her yerinde ek ağ isteği yapmadan bu veriye erişebilirsiniz. ```typescript showLineNumbers class SubscriptionManager { private currentProfile: any = null; constructor() { // Listen for profile updates adapty.addListener('onLatestProfileLoad', (data) => { this.currentProfile = data.profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() hasAccess(): boolean { return this.currentProfile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive ?? false; } } ``` :::note Adapty, uygulamanız başladığında `onLatestProfileLoad` event listener'ını otomatik olarak çağırır; bu sayede cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verisi sağlanır. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim izni verme konusunda anlık kararlar almanız gerektiğinde, kullanıcı profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere giriş veya belirli içerikler gösterilmeden önce gibi senaryolarda oldukça kullanışlıdır. ```typescript showLineNumbers const checkAccessLevel = async () => { try { const profile = await adapty.getProfile(); return profile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive === true; } catch (error) { console.warn('Error checking access level:', error); return false; // Show paywall if access check fails } }; const getAccessLevel = (profile: AdaptyProfile) => { return profile.accessLevels?.['YOUR_ACCESS_LEVEL']; }; const initializePaywall = async () => { try { await loadPaywall(); const hasAccess = await checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } catch (error) { console.warn('Error initializing paywall:', error); } }; ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların satın aldıklarına erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](capacitor-quickstart-identify) incelemeye başlayabilirsiniz. --- # File: capacitor-quickstart-identify --- --- title: "Capacitor SDK'da kullanıcıları tanımlama" description: "Capacitor'da uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- Kullanıcıların satın almalarını nasıl yönettiğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız backend kimlik doğrulaması kullanmıyor ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılarla ilgili bölüme](#anonymous-users) bakın. - Uygulamanızda backend kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılarla ilgili bölüme](#identified-users) bakın. :::tip **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. Anonim (customer user ID'siz) veya tanımlı (customer user ID'li) olabilirler. - **Customer user ID'ler**, kullanıcılarınızı Adapty profillerine bağlamak için **sizin oluşturduğunuz** isteğe bağlı tanımlayıcılardır. ::: Anonim ve tanımlı kullanıcılar arasındaki farklar şunlardır: | | Anonim kullanıcılar | Tanımlı kullanıcılar | |-------------------------|---------------------------------------------------------------|---------------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Müşteri kullanıcı kimliği aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar genelinde aynı profil | | **Veri kalıcılığı** | Anonim kullanıcıların verileri cihaza/kuruluma bağlıdır | Tanımlı kullanıcıların verileri cihazlar ve oturumlar genelinde kalıcıdır | ## Anonim kullanıcılar \{#anonymous-users\} Bir backend kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulama içinde herhangi bir şey satın aldığında, bu satın alma **kullanıcının Adapty profili ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** kurduğunda, Adapty **etkinleştirme sırasında yeni ve boş bir profil oluşturur**. 4. Kullanıcı daha önce uygulamanızdan satın alma yapmışsa, bu satın almalar varsayılan olarak SDK etkinleştirildiğinde App Store'dan otomatik olarak senkronize edilir. :::note Yedekten geri yükleme işlemleri, yeniden kurulumdan farklı davranır. Varsayılan olarak, bir kullanıcı yedekten geri yükleme yaptığında SDK önbelleğe alınmış verileri korur ve yeni bir profil oluşturmaz. Bu davranışı `clearDataOnBackup` ayarını kullanarak yapılandırabilirsiniz. [Daha fazla bilgi](sdk-installation-capacitor#clear-data-on-backup-restore). ::: ## Tanımlanan kullanıcılar \{#identified-users\} - Bir profilin henüz customer user ID'si yoksa (yani **kullanıcı oturum açmamışsa**), bir customer user ID gönderdiğinizde bu ID söz konusu profille ilişkilendirilir. - Bu bir **yeniden kurulum, oturum açma veya yeni bir cihazdan kurulumsa** ve daha önce o kullanıcının customer user ID'sini gönderdiyseniz, yeni bir profil oluşturulmaz. Bunun yerine, customer user ID ile ilişkilendirilmiş mevcut profile geçiş yapılır. Uygulamada kullanıcıları tanımlamak için iki seçeneğiniz var: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulama başladıktan sonra giriş yapıyorsa, kimlik doğrulama sırasında bir müşteri kullanıcı kimliğiyle `identify()` işlevini çağırın. - [**SDK etkinleştirme sırasında:**](#during-the-sdk-activation) Uygulama başlarken halihazırda bir müşteri kullanıcı kimliğiniz varsa, `activate()` çağrısı yaparken bunu gönderin. :::important Varsayılan olarak, Adapty bir satın alma işlemini başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den aldığında, access level paylaşılır; yani her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak ya da paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Daha fazla bilgi için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kaydolduktan sonra), müşteri kullanıcı kimliğini ayarlamak için `identify` metodunu kullanın. - Bu müşteri kullanıcı kimliğini **daha önce kullanmadıysanız**, Adapty bunu otomatik olarak mevcut profille ilişkilendirir. - Bu müşteri kullanıcı kimliğini **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu müşteri kullanıcı kimliğiyle ilişkili profille çalışmaya geçer. :::tip Bir müşteri kullanıcı kimliği oluştururken, bunu kullanıcı verilerinizle birlikte kaydedin. Böylece yeni bir cihazdan giriş yaptıklarında veya uygulamayı yeniden yüklediklerinde aynı kimliği gönderebilirsiniz. ::: Diğer SDK metodlarını çağırmadan önce her zaman `identify` metodunu `await` ile bekleyin. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar ya da anonim profile düşer. Daha fazla bilgi için bkz. [Capacitor SDK'da çağrı sırası](capacitor-sdk-call-order). ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` ### SDK etkinleştirme sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde müşteri kullanıcı kimliğini zaten biliyorsanız, `identify` metodunu ayrıca çağırmak yerine doğrudan `activate` metodunda gönderebilirsiniz. Müşteri kullanıcı kimliğini bilmenize rağmen bunu etkinleştirmeden sonra ayarlıyorsanız, etkinleştirme anında Adapty yeni bir boş profil oluşturur ve `identify` metodunu çağırdıktan sonra mevcut profile geçer. Mevcut bir müşteri kullanıcı kimliği (daha önce kullandığınız) ya da yeni bir tane girebilirsiniz. Yeni bir tane girerseniz, aktivasyon sırasında oluşturulan yeni profil otomatik olarak müşteri kullanıcı kimliğine bağlanır. :::tip Oluşturulan boş profilleri kontrol paneli analizlerinden dışlamak için **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın. ::: ```typescript showLineNumbers await adapty.activate({ apiKey: "YOUR_PUBLIC_SDK_KEY", params: { customerUserId: "YOUR_USER_ID" } }); ``` ### Kullanıcı oturumunu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir butonunuz varsa, `logout` metodunu kullanın. Bu işlem kullanıcı için yeni bir anonim profil kimliği oluşturur. ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` :::info Kullanıcıları uygulamaya tekrar giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın alma izni \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce de sonra da satın alma yapabiliyorsa, ek bir kurulum yapmanıza gerek yok: İşte nasıl çalıştığı: 1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil ID'sine bağlar. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), Adapty işlemleri otomatik olarak senkronize eder. - Yeni bir customer user ID ise (örneğin, satın alma kayıt olmadan önce yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. --- # File: adapty-sdk-integration-skill-capacitor --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Capacitor uygulamanıza entegre edin" description: "AI kodlama aracınızla Adapty SDK'yı Capacitor uygulamanıza uçtan uca entegre etmek için adapty-sdk-integration becerisini kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu özellik beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, AI aracınızı her adımda doğru belgelerle yönlendiren [adım adım entegrasyon kılavuzunu](adapty-cursor-capacitor) takip edin. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-capacitor --- --- title: "Adapty'yi AI yardımıyla Capacitor uygulamanıza entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi Capacitor uygulamanıza entegre etmek için adım adım kılavuz." --- Bu kılavuz, bir yapay zeka kodlama aracıyla Adapty'yi Capacitor uygulamanıza adım adım entegre etmenizi sağlar; bunun için doğru Adapty dokümanlarını doğru sırayla beslemeniz yeterli. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce bazı kontrol paneli ayarlarının yapılmasını gerektirir. Bunu etkileşimli bir LLM aracıyla veya Kontrol Paneli üzerinden manuel olarak gerçekleştirebilirsiniz. ### Beceri yaklaşımı (önerilir) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywalllarınızı ve placement'larınızı doğrudan ayarlamasına olanak tanır — her adım için Kontrol Paneli'ni açmanıza gerek kalmaz. Yalnızca [mağazalarınızı bağlamanız](integrate-payments) gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra, ajansınızda `/adapty-cli` komutunu çalıştırın. Mağazalarınızı bağlamak için Kontrol Paneli'ni ne zaman açmanız gerektiği de dahil olmak üzere her adımda sizi yönlendirecektir. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Eğer her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, herhangi bir kod yazmadan önce almanız gerekenler şunlardır. LLM'iniz kontrol paneli değerlerini sizin için arayamaz — bunları kendiniz sağlamanız gerekecek. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Capacitor uygulamanız her iki platformu da hedefliyorsa hem App Store hem de Google Play'i bağlayın. Bu, satın alma işlemlerinin çalışması için zorunludur. [Uygulama mağazalarını bağla](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin, ardından **API keys** kısmını bulun. Kodda bu, `adapty.activate()` fonksiyonuna ilettiğiniz dizedir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere kodda doğrudan erişmezsiniz — Adapty bunları paywall'lar aracılığıyla iletir. [Ürün ekle](quickstart-products) 4. **Bir paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasında bir paywall oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `adapty.getFlow()` fonksiyonuna geçirdiğiniz string değerdir. [Paywall oluşturun](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde, **Products** sayfasında her ürün için yapılandırın. Kodda, `profile.accessLevels['premium']?.isActive` içinde kontrol edilen string budur. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar, ürüne bağlı olarak farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Beşini de aldıktan sonra kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve flow çekme kodunu üretebilir. ::: ### Hazır olduğunuzda yapılandırın \{#set-up-when-ready\} Kodlamaya başlamak için bunlar zorunlu değil, ancak entegrasyonunuz olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonlar**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonlar](analytics-integration) ve [attribution entegrasyonlar](attribution-integration). ## LLM'nize Adapty Dokümanlarını Besleyin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi Kullanın (önerilen) [Context7](https://context7.com), LLM'inize güncel Adapty belgelerine doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, ne sorduğunuza göre doğru belgeleri otomatik olarak getirir — manuel URL yapıştırmaya gerek yoktur. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurulum için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, Adapty kütüphanesine prompt'larınızda referans verin: ``` Use the adaptyteam/adapty-docs library to look up how to install the Capacitor SDK ``` :::warning Context7, belge bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin doğru çalıştığından emin olmak için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Her Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** düğmesine tıklayın. Örneğin: [adapty-cursor-capacitor.md](https://adapty.io/docs/tr/adapty-cursor-capacitor.md). Aşağıdaki [uygulama adım adım kılavuzundaki](#implementation-walkthrough) her aşama, yapıştırabileceğiniz `.md` bağlantılarını içeren bir "Bunu LLM'inize gönderin" bloğu içerir. Aynı anda daha fazla dokümana ulaşmak için aşağıdaki [indeks dosyalarına ve platforma özgü alt kümelere](#plain-text-doc-index-files) bakın. ## Uygulama adım adım \{#implementation-walkthrough\} Bu kılavuzun geri kalanı, Adapty entegrasyonunu uygulama sırasına göre adım adım ele alır. Her aşamada LLM'inize göndereceğiniz belgeler, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar açıklanmaktadır. ### Entegrasyonu planlayın \{#plan-your-integration\} Koda geçmeden önce LLM'inize projenizi analiz ettirin ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor veya Claude Code'un plan modu gibi), LLM'in herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin; bu, takip etmesi gereken kılavuzları etkiler: - [**Adapty Flow Builder**](adapty-flow-builder): Flow'ları Adapty'nin no-code builder'ında oluşturursunuz, SDK bunları otomatik olarak işler. - [**Manuel oluşturulan paywall'lar**](capacitor-making-purchases): Kendi paywall arayüzünüzü kodla oluşturursunuz, ancak ürünleri getirmek ve satın almaları yönetmek için Adapty'yi kullanırsınız. - [**Observer modu**](observer-vs-full-mode): Mevcut satın alma altyapınızı korursunuz ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](capacitor-quickstart-paywalls) okuyun. ### SDK'yı kurun ve yapılandırın \{#install-and-configure-the-sdk\} npm ile Adapty SDK bağımlılığını ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temel adımdır — diğer her şey buna bağlıdır. **Rehber:** [Adapty SDK'yı kurun ve yapılandırın](sdk-installation-capacitor) :::info Bu rehber, Adapty Capacitor SDK v4 (beta) hedeflemektedir — API, [hızlı başlangıç](capacitor-quickstart-paywalls) kılavuzu tarafından anlatılmaktadır. v4 bir ön sürümdür, bu nedenle LLM'inizin en son kararlı 3.x sürümünü yüklemek yerine tam sürümü (`npm install @adapty/capacitor@4.0.0-beta.2`) sabitlediğinden emin olun. [SDK 4.0 kurulum bölümüne](sdk-installation-capacitor#adapty-sdk-40-beta) ve [geçiş kılavuzuna](migration-to-capacitor-sdk-v4) bakın. ::: Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-capacitor.md ``` :::tip[Checkpoint] - **Beklenen:** Uygulama hem iOS hem Android'de derlenir ve çalışır. Konsol, Adapty aktivasyon logunu gösterir. - **Dikkat:** "Public API key is missing" → **App settings** sayfasından aldığınız gerçek anahtarla placeholder'ı değiştirdiğinizi kontrol edin. ::: ### Paywall'ları göster ve satın almaları yönet \{#show-paywalls-and-handle-purchases\} Placement ID ile paywall çekip göster ve satın alma olaylarını yönet. İhtiyacın olan kılavuzlar, satın almaları nasıl yönettiğine bağlı. Her satın almayı ilerlerken sandbox ortamında test et — sona bırakma. Kurulum talimatları için bkz. [Sandbox'ta satın alma testi](test-purchases-in-sandbox). <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Flow Builder" default> **Kılavuzlar:** - [Flow ve paywall'ları etkinleştirme (hızlı başlangıç)](capacitor-quickstart-paywalls) - [Flow ve paywall'ları alma](capacitor-get-pb-paywalls) - [Flow ve paywall'ları gösterme](capacitor-present-paywalls) - [Olayları yönetme](capacitor-handling-events) - [Eylemlere yanıt verme](capacitor-handle-paywall-actions) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/capacitor-quickstart-paywalls.md - https://adapty.io/docs/tr/capacitor-get-pb-paywalls.md - https://adapty.io/docs/tr/capacitor-present-paywalls.md - https://adapty.io/docs/tr/capacitor-handling-events.md - https://adapty.io/docs/tr/capacitor-handle-paywall-actions.md ``` :::tip[Checkpoint] - **Beklenen:** Flow, yapılandırdığınız ürünlerle görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikler. - **Dikkat:** Boş flow veya `getFlow` hatası → placement ID'sinin kontrol paneliyle birebir eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **Kılavuzlar:** - [Özel paywallınızda satın almaları etkinleştirin (hızlı başlangıç)](capacitor-quickstart-manual) - [Paywallları ve ürünleri getirin](fetch-paywalls-and-products-capacitor) - [Remote config ile tasarlanmış paywall'ı gösterin](present-remote-config-paywalls-capacitor) - [Satın alma yapın](capacitor-making-purchases) - [Satın almaları geri yükleyin](capacitor-restore-purchase) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/capacitor-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-capacitor.md - https://adapty.io/docs/tr/present-remote-config-paywalls-capacitor.md - https://adapty.io/docs/tr/capacitor-making-purchases.md - https://adapty.io/docs/tr/capacitor-restore-purchase.md ``` :::tip[Checkpoint] - **Beklenen:** Özel paywallınız, Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikliyor. - **Sorun:** Boş ürünler dizisi → paywallın kontrol panelinde atanmış ürünleri olduğunu ve placement'ın bir kitlesi bulunduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Observer mode"> **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode-capacitor) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode-capacitor) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-capacitor.md - https://adapty.io/docs/tr/report-transactions-observer-mode-capacitor.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak sandbox ortamında bir satın alma yaptıktan sonra işlem, Adapty kontrol panelinin **Event Feed** bölümünde görünmelidir. - **Dikkat:** Hiç etkinlik yoksa → Adapty'e işlem raporladığınızı ve her iki mağaza için de sunucu bildirimlerinin yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol et \{#check-subscription-status\} Satın alma işleminin ardından, premium içeriğe erişimi kısıtlamak için kullanıcı profilinde aktif bir access level olup olmadığını kontrol et. **Rehber:** [Abonelik durumunu kontrol et](capacitor-check-subscription-status) Bunu LLM'ine gönder: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/capacitor-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın almasından sonra `profile.accessLevels['premium']?.isActive` değeri `true` döner. - **Dikkat:** Satın alma sonrasında `accessLevels` boş geliyorsa → ürünün kontrol panelinde bir access level atanıp atanmadığını kontrol et. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Uygulama kullanıcı hesaplarını Adapty profillerine bağlayarak satın alımların cihazlar arasında kalıcı olmasını sağlayın. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](capacitor-quickstart-identify) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/capacitor-quickstart-identify.md ``` :::tip[Checkpoint] - **Beklenen:** `adapty.identify()` çağrısının ardından, kontrol panelindeki **Profiles** bölümünde özel kullanıcı ID'niz görünür. - **Dikkat:** Anonim profil attribution'ından kaçınmak için `identify`'ı aktivasyondan sonra, ancak paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlanma \{#prepare-for-release\} Entegrasyonunuz sandbox ortamında düzgün çalıştıktan sonra, her şeyin canlı ortama hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Kılavuz:** [Yayın kontrol listesi](release-checklist) Bunu LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Checkpoint] - **Beklenen:** Tüm kontrol listesi öğeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Eksik sunucu bildirimleri → App Store Server Notifications'ı **App settings → iOS SDK** bölümünde, Google Play Real-Time Developer Notifications'ı ise **App settings → Android SDK** bölümünde yapılandırın. ::: ## Düz metin belge dizin dosyaları \{#plain-text-doc-index-files\} Büyük dil modelinize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamak istiyorsanız, tüm Adapty belgelerini listeleyen veya bir araya getiren dizin dosyaları sunuyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı yapay zeka ajanlarında (ör. ChatGPT) `llms.txt` dosyasını indirip sohbete dosya olarak yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hâlde. Çok büyük — yalnızca tüm içeriğe ihtiyaç duyduğunuzda kullanın. - Capacitor'a özgü [`capacitor-llms.txt`](https://adapty.io/docs/tr/capacitor-llms.txt) ve [`capacitor-llms-full.txt`](https://adapty.io/docs/tr/capacitor-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: capacitor-paywalls --- --- title: "Flow'lar ve paywalllar - Capacitor" description: "Capacitor uygulamanızda Adapty Flow Builder veya Paywall Builder ile oluşturulmuş flow'ları ve paywallları görüntüleyin ve yönetin." --- ## Paywallları görüntüleme \{#display-paywalls\} ### Adapty Flow Builder & Paywall Builder \{#adapty-flow-builder--paywall-builder\} <CustomDocCardList ids={['capacitor-get-pb-paywalls', 'capacitor-present-paywalls', 'capacitor-handling-events', 'capacitor-handle-paywall-actions']} /> :::tip Adapty flow'larını ve paywalllarını hızlıca kullanmaya başlamak için [hızlı başlangıç kılavuzumuza](capacitor-quickstart-paywalls) göz atın. ::: ### Paywallları manuel olarak uygulama \{#implement-paywalls-manually\} <CustomDocCardList ids={['capacitor-quickstart-manual', 'fetch-paywalls-and-products-capacitor', 'present-remote-config-paywalls-capacitor', 'capacitor-making-purchases']} /> Paywallları uygulama ve satın alma işlemlerini manuel olarak yönetme hakkında daha fazla rehber için [kategoriye](capacitor-implement-paywalls-manually) bakın. ## Kullanışlı özellikler \{#useful-features\} <CustomDocCardList ids={['capacitor-use-fallback-paywalls', 'capacitor-web-paywall']} /> --- # File: capacitor-get-pb-paywalls --- --- title: "Flow ve paywall alma - Capacitor" description: "Capacitor uygulamanızda Adapty'den flow ve paywall verilerini alın." --- <SDKv4> <MethodPromo method="getFlow" /> [Flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'ı ve görünüm yapılandırmasını almaktır. Bu konunun flow'lar ve Paywall Builder ile özelleştirilmiş paywalllar için geçerli olduğunu lütfen unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, [Mobil uygulamanızda remote config paywallları için paywallları ve ürünleri getirme](fetch-paywalls-and-products-capacitor) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları ve paywall'ları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-capacitor)'yı yükleyin. </details> ## Flow/paywall'ı getirme \{#fetch-flowpaywall\} Flow Builder veya Paywall Builder ile bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir flow veya paywall, içinde neyin ve nasıl gösterileceği bilgisini zaten barındırır. Bununla birlikte, placement üzerinden ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir. Flow veya paywall'ı mümkün olduğunca erken — ideal olarak sunmadan çok önce — çekin ve [view'unu](capacitor-get-pb-paywalls#fetch-the-view-configuration) oluşturun. `createFlowView` metodu, view yapılandırmasını yükler ve arka planda görsellerini indirip önbelleğe almaya başlar. Bu metodu ne kadar erken çağırırsanız, indirmelerin tamamlanması için o kadar çok zaman kalır. Flow veya paywall'ı sunduğunuzda, yapılandırma ve görseller zaten önbellekte hazır olabilir. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```typescript showLineNumbers try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', }); // istenen flow/paywall } catch (error) { // hatayı işle } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |-------------------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `'reload_revalidating_cache_data'` | <p>İsteğe bağlı `params` nesnesinin içinde iletilir. Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış veriyi döndürür. Bu varyantı kullanmanızı öneririz, çünkü kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, mevcut olması durumunda önbelleğe alınmış veriyi döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu senaryoda kullanıcılar her zaman en güncel verilere ulaşamayabilir; ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak amacıyla oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Paywall'ları daha hızlı getirmek için CDN, CDN'ye ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, paywall'larınızın her zaman en güncel sürümünü almanızı sağlarken internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği koruyacak şekilde tasarlanmıştır.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>İsteğe bağlı `params` nesnesinin içinde iletilir. Bu değer, söz konusu yöntem için zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu yöntemin `loadTimeoutMs` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem, arka planda farklı isteklerden oluşabilir.</p> | **Ürün ID'lerini kodun içine gömmeyин.** Kodun içine gömmeniz gereken tek şey placement ID'sidir. Flow'lar ve paywall'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir paywall bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Flow'un tanımlayıcılarını (`id`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve remote config'leri (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## Görünüm yapılandırmasını getir \{#fetch-the-view-configuration\} :::important Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm yapılandırması alınamaz. ::: Placement **Flow Builder** veya **Paywall Builder** ile tasarlandıysa, Adapty arayüzü sizin için oluşturur. `createFlowView` ile görünümü oluşturun, ardından [flow veya paywall'ı gösterin](capacitor-present-paywalls). Placement, Builder arayüzü olmayan özel bir paywall ise bunun yerine [remote config paywall olarak işleyin](present-remote-config-paywalls-capacitor). Capacitor SDK'sında, view yapılandırmasını önceden almanıza gerek yoktur; `createFlowView` metodunu doğrudan çağırabilirsiniz. :::warning `createFlowView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `createFlowView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak hataya yol açabilir. ::: ```typescript showLineNumbers try { const view = await createFlowView(flow); } catch (error) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | zorunlu | İstenen flow/paywall için controller elde etmek üzere kullanılan `AdaptyFlow` nesnesi. | | **customTags** | opsiyonel | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlar. Özel etiketler, içerikteki yer tutucular olarak işlev görür ve flow/paywall içinde kişiselleştirilmiş içerik sunmak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için Paywall Builder'da özel etiketler konusuna bakın. | | **prefetchProducts** | opsiyonel | Ürünlerin ekranda gösterilme zamanlamasını optimize etmek için etkinleştirin. `true` olduğunda AdaptyUI gerekli ürünleri otomatik olarak çeker. Varsayılan: `true`. | | **android.enableSafeArea** | opsiyonel | Yalnızca Android (iOS'ta yoksayılır). `android` anahtarı altında yer alır. `true` olduğunda flow görünümü güvenli alan dolgularını uygular. Varsayılan: `true`. Varsayılan değer çoğu durum için uygundur. | :::note Birden fazla dil kullanıyorsanız, [flow yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve yerel ayar kodlarını nasıl doğru kullanacağınızı [buradan](capacitor-localizations-and-locale-codes) öğrenin. ::: Görünümü elde ettikten sonra [flow/paywall'ı gösterin](capacitor-present-paywalls). ## Varsayılan kitle için flow veya paywall getirerek daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında getirilir, bu nedenle bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak kritik önem taşır: önerilen yaklaşım, yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklanan `getFlow` metoduyla flow veya paywall'ı getirmektir. :::warning Neden `getFlow` kullanmanızı öneririz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Potansiyel geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecekteki) farklı paywall'lar göstermeniz gerekirse, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecektir; bu da ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı flow veya paywall yükleme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```typescript showLineNumbers try { const flow = await adapty.getFlowForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested flow/paywall } catch (error) { // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `'reload_revalidating_cache_data'` | <p>İsteğe bağlı `params` nesnesi içinde iletilir. SDK varsayılan olarak sunucudan veri yüklemeye çalışır; hata durumunda önbellekteki veriyi döner. Bu seçeneği öneriyoruz çünkü kullanıcılarınızın her zaman en güncel veriye erişmesini sağlar.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en son veriyi alamayabilir; ama internet bağlantısı ne kadar tutarsız olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerini azaltmak amacıyla oturum boyunca güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini unutmayın; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlenir.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Flow/paywall'ınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videolar, önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde bu öğeleri ID'leri aracılığıyla hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video göstermek. - Uzaktaki ana görsel yüklenirken yerel bir önizleme görseli göstermek. - Video oynatılmadan önce bir önizleme görseli göstermek. İşte özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```typescript showLineNumbers const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; const view = await createFlowView(flow, { customAssets }); ``` :::note Bir varlık bulunamazsa, flow/paywall varsayılan görünümüne geri döner. ::: </SDKv4> <SDKv3> [Adapty Kontrol Paneli'ndeki yeni Paywall Builder ile paywallınızın görsel kısmını tasarladıktan sonra](adapty-paywall-builder), onu mobil uygulamanızda görüntüleyebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywallı ve görünüm yapılandırmasını almaktır. Lütfen bu konunun Paywall Builder ile özelleştirilmiş paywallları kapsadığını unutmayın. Remote config paywalllarını getirme hakkında bilgi için [Mobil uygulamanızda remote config paywallları için paywall ve ürünleri getirme](fetch-paywalls-and-products-capacitor) konusuna bakın. <details> <summary>Mobil uygulamanızda paywall göstermeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-capacitor) yükleyin. </details> ## Paywall Builder ile Tasarlanmış Paywall'ı Getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder ile bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etmeniz gerekmez. Böyle bir paywall, hem gösterilecek içeriği hem de nasıl gösterileceğini içerir. Bununla birlikte, paywall'ın ID'sini placement aracılığıyla, görünüm yapılandırmasını ise ayrıca almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, paywall'u ve onun [görünüm yapılandırmasını](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız kritik önem taşır; böylece görseller kullanıcıya sunulmadan önce indirilmesi için yeterli zaman olur. Bir paywall almak için `getPaywall` metodunu kullanın: ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // istenen paywall } catch (error) { // hatayı işle } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge için kullanılır.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.</p> | | **params** | isteğe bağlı | Paywall'u getirmek için ek parametreler. | **Ürün ID'lerini sabit kodlamayın.** Sabit kodlamanız gereken tek ID, placement ID'sidir. Paywall'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir paywall bugün iki ürün, yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini göstermelidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Ürün kimliklerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer birçok özelliği içeren bir [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) nesnesidir. | ## Paywall Builder ile tasarlanmış paywall'ın görünüm konfigürasyonunu alma \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm konfigürasyonu alınamaz. ::: Paywall'ı aldıktan sonra, Paywall Builder kullanılarak oluşturulduğunu belirten `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywall'ı nasıl göstereceğiniz konusunda size yol gösterecektir. `ViewConfiguration` mevcutsa Paywall Builder paywall'ı olarak işleyin; değilse, [remote config paywall olarak ele alın](present-remote-config-paywalls-capacitor). Capacitor SDK'da, view configuration'ı manuel olarak önceden almadan doğrudan `createPaywallView` metodunu çağırın. :::warning `createPaywallView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa, `createPaywallView` metodunu yeniden çağırın. ::: ```typescript showLineNumbers if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { // use your custom logic } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir controller elde etmek üzere kullanılan `AdaptyPaywall` nesnesi. | | **customTags** | isteğe bağlı | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlar. Özel etiketler, paywall içeriğinde yer tutucu olarak işlev görür ve paywall içinde kişiselleştirilmiş içerik sunmak için belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için Paywall builder'da özel etiketler konusuna bakın. | | **prefetchProducts** | isteğe bağlı | Ekranda ürünlerin görüntülenme zamanlamasını optimize etmek için etkinleştirin. `true` olarak ayarlandığında AdaptyUI, gerekli ürünleri otomatik olarak getirir. Varsayılan: `false`. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve yerel ayar kodlarını doğru kullanmayı [buradan](capacitor-localizations-and-locale-codes) öğrenebilirsiniz. ::: Görünümü elde ettikten sonra [paywalli gösterin](capacitor-present-paywalls). ## Varsayılan kitle için paywallı daha hızlı getir \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle paywalllar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir paywallı getirmek istediğinizden daha uzun sürebilir. Bu durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın paywall'ını **All Users** kitlesi için getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu bilmeniz önemlidir: önerilen yaklaşım, paywall'ı yukarıdaki [Paywall Bilgisini Getirme](#fetch-paywall-designed-with-paywall-builder) bölümünde açıklandığı gibi `getPaywall` metoduyla getirmektir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa, mevcut (eski) sürümü destekleyen paywall'lar tasarlamak ya da mevcut (eski) sürümdeki kullanıcıların oluşturulamayan paywall'larla sorun yaşayabileceğini kabul etmek zorunda kalırsınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları göze alarak daha hızlı paywall yüklemenin avantajından yararlanmak istiyorsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // istenen paywall } catch (error) { // hatayı işleyin } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](capacitor-localizations-and-locale-codes) bölümüne bakın.</p> | | **params** | isteğe bağlı | Paywall'ı getirmek için ek parametreler. | ## Varlıkları özelleştirin \{#customize-assets\} Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videoların önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde bu öğeleri ID'lerine göre hedefleyerek davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID ayarlamanız](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterebilirsiniz. - Uzaktaki ana görsel yüklenirken yerel bir önizleme görseli gösterebilirsiniz. - Video başlamadan önce bir önizleme görseli gösterebilirsiniz. İşte özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```typescript showLineNumbers const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; view = await createPaywallView(paywall, { customAssets }); ``` :::note Bir varlık bulunamazsa, paywall varsayılan görünümüne geri döner. ::: </SDKv3> --- # File: capacitor-present-paywalls --- --- title: "Flow ve paywallları görüntüle - Capacitor" description: "Adapty ile Capacitor uygulamanızda kullanıcılara flow ve paywallları sunun." --- <SDKv4> Flow Builder'da bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir flow, içinde ne gösterileceğini ve nasıl gösterileceğini zaten barındırır. Başlamadan önce şunlardan emin olun: 1. [Bir flow veya paywall oluşturduğunuzdan](create-paywall). 2. Bunu bir [placement](placements)'a eklediğinizden. 3. [Flow'u fetch edip view'ı hazırladığınızdan](capacitor-get-pb-paywalls). :::warning Bu kılavuz yalnızca **flow'lar ve Paywall Builder paywallları** içindir; SDK v4.0 veya üzeri gerektirir. Flow'ların sunulma süreci, remote config paywalllarından farklıdır. - **Remote config paywalllarını** sunmak için bkz. [Remote config ile tasarlanmış paywallı göster](present-remote-config-paywalls-capacitor). ::: Bir flow veya paywall'ı bağımsız bir ekran olarak görüntülemek için, [`createFlowView`](capacitor-get-pb-paywalls#fetch-the-view-configuration) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Flow'u tekrar görüntülemeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createFlowView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan kullanmak yasaktır. Bu bir hataya yol açar. ::: ```typescript showLineNumbers const view = await createFlowView(flow); // İsteğe bağlı: flow olaylarını yönetin (kapat, satın alma, geri yükleme, vb.) // await view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // hatayı yönetin } ``` :::important `setEventHandlers` fonksiyonunu birden fazla kez çağırmak, sağladığınız işleyicilerin üzerine yazar; bu durum hem varsayılan hem de daha önce belirli olaylar için ayarlanmış işleyicilerin yerini alır. ::: ## iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek flow'un iOS'ta nasıl sunulacağını yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. Android'de flow'lar her zaman tam ekran activity olarak görüntülenir. ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## Geliştirici tanımlı zamanlayıcı kullanma \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcıları kullanmak için `timerId` değerini, bu örnekte `CUSTOM_TIMER_NY`'yi kullanın; bu, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. Bu sayede uygulamanız zamanlayıcıyı doğru değerle (örneğin, zamanlayıcının bitiş zamanı olan Yılbaşı gününden mevcut zamanın çıkarılmasıyla hesaplanan `13d 09h 03m 34s` gibi) dinamik olarak günceller. ```typescript showLineNumbers const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createFlowView(flow, { customTimers }); ``` Bu örnekte `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. Zamanlayıcı, uygulamanızın zamanlayıcıyı doğru değerle (örneğin, zamanlayıcının bitiş zamanı olan Yılbaşı gününden mevcut zamanın çıkarılmasıyla hesaplanan `13d 09h 03m 34s` gibi) dinamik olarak güncellemesini sağlar. ## İletişim kutusunu göster \{#show-dialog\} Android'de bir flow görünümü sunulduğunda, native uyarı iletişim kutuları yerine bu yöntemi kullanın. Android'de normal uyarılar, flow görünümünün arkasında görünür ve bu da kullanıcılar tarafından görülememelerine neden olur. Bu yöntem, tüm platformlarda flow'un üzerinde iletişim kutusunun doğru şekilde gösterilmesini sağlar. ```typescript showLineNumbers try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the flow await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## Bir aboneliği diğeriyle değiştirme \{#replace-one-subscription-with-another\} Android'de bir kullanıcı aktif bir aboneliği varken yeni bir abonelik satın almaya çalıştığında, flow view oluşturulurken abonelik güncelleme parametreleri geçirerek yeni satın alma işleminin nasıl ele alınacağını kontrol edebilirsiniz. Mevcut aboneliği yenisiyle değiştirmek için `createFlowView` içinde `productPurchaseParams` kullanırken `oldSubVendorProductId` ve `prorationMode` parametrelerini belirtin. ```typescript showLineNumbers const productPurchaseParams = flow.paywalls .flatMap((paywall) => paywall.productIdentifiers) .map((productId) => { const params: MakePurchaseParamsInput = {}; if (Capacitor.getPlatform() === 'android') { params.android = { subscriptionUpdateParams: { oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION', prorationMode: 'with_time_proration', }, }; } return { productId, params }; }); const view = await createFlowView(flow, { productPurchaseParams }); ``` </SDKv4> <SDKv3> Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir paywall, hem içeriği hem de görüntülenme biçimini barındırır. :::warning Bu kılavuz yalnızca **Paywall Builder paywallları** içindir. Remote config paywallları için sunum süreci farklıdır. **Remote config paywalllarını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls). ::: Bir paywall'ı görüntülemek için, [`createPaywallView`](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metodu ile oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar görüntülemeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createPaywallView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan kullanmak hataya yol açabilir. ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; }, }); try { await view.present(); } catch (error) { // handle the error } ``` ## Geliştirici tanımlı zamanlayıcıyı kullanma \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcıları kullanmak için `timerId`'yi, bu örnekte `CUSTOM_TIMER_NY`'yi, yani Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sini kullanın. Bu sayede uygulamanız zamanlayıcıyı doğru değerle dinamik olarak günceller; örneğin `13d 09h 03m 34s` (zamanlayıcının bitiş zamanı olan Yılbaşı gibi bir tarihin, o anki zamandan çıkarılmasıyla hesaplanır). ```typescript showLineNumbers const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createPaywallView(paywall, { customTimers }); ``` Bu örnekte, `CUSTOM_TIMER_NY` Adapty kontrol panelinde belirlediğiniz geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. Zamanlayıcı, uygulamanızın zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar—örneğin `13d 09h 03m 34s` (zamanlayıcının bitiş saatinden, Yılbaşı gibi, mevcut zaman çıkarılarak hesaplanır). ## İletişim kutusu gösterme \{#show-dialog\} Android'de bir paywall görünümü sunulduğunda, yerel uyarı iletişim kutuları yerine bu metodu kullanın. Android'de normal uyarılar paywall görünümünün arkasında göründüğünden kullanıcılar tarafından görülemez. Bu metod, tüm platformlarda iletişim kutusunun paywall'ın üzerinde doğru şekilde gösterilmesini sağlar. ```typescript showLineNumbers title="Capacitor" try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `iosPresentationStyle` parametresini `present()` metoduna geçirerek paywallın iOS'ta nasıl sunulacağını yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` </SDKv3> --- # File: capacitor-handle-paywall-actions --- --- title: "Flow aksiyonlarına yanıt verme - Capacitor" description: "Capacitor'da Adapty kullanarak flow'lardan ve paywall'lardan gelen buton aksiyonlarını yönetin, uygulama monetizasyonunu iyileştirin." --- <SDKv4> Adapty [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) kullanarak flow'lar ya da paywall'lar oluşturuyorsanız, butonları doğru şekilde ayarlamak çok önemlidir: 1. [Builder'da bir buton ekleyin](paywall-buttons) ve ona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve mevcut eylemlerin kodunuzda nasıl işleneceğini gösterir. :::warning **Satın almalar, geri yüklemeler, flow ve paywall kapatma işlemleri ile URL açma otomatik olarak gerçekleştirilir.** Varsayılan davranışlarını yapılandırabilir ya da özel eylemler için yanıtlar uygulayabilirsiniz. ::: :::note Bir olay için handler ayarlamak, o olayın varsayılan davranışının tamamen yerine geçer. Ayarlamadığınız handler'lar varsayılan davranışlarını korur. ::: ## Flow ve paywall'ları kapatma \{#close-flows-and-paywalls\} Flow veya paywall'ınıza kapatma düğmesi eklemek için: 1. Builder'da bir düğme ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda, flow veya paywall'ı kapatan `close` eylemi için bir işleyici uygulayın. :::info Capacitor SDK'da `close` eylemi, varsayılan olarak flow veya paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir flow'u kapatmak başka bir flow'un açılmasını tetikleyebilir. ::: ```typescript showLineNumbers const view = await createFlowView(flow); const unsubscribe = await view.setEventHandlers({ onCloseButtonPress() { return true; // allow the flow to close }, }); ``` Android'de sistem **Geri** düğmesi ve geri hareketi ayrı bir `onAndroidSystemBack` olayını tetikler. SDK v4'te bu olay artık varsayılan olarak flow'u kapatmaz. **Geri** düğmesinin flow'u kapatmasını istiyorsanız handler'dan `true` döndürün: ```typescript showLineNumbers const unsubscribe = await view.setEventHandlers({ onAndroidSystemBack() { return true; // close the flow when the Back button is pressed }, }); ``` ## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma iadesi), builder'da bir **Link** elementi ekleyin ve bunu **Open URL** aksiyonuyla butonlarla aynı şekilde ele alın. ::: Flow'unuzdan veya paywall'ınızdan bir bağlantı açan buton eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Builder'da bir buton ekleyin, **Open URL** aksiyonunu atayın ve açmak istediğiniz URL'yi girin. 2. Gerekirse, uygulama kodunuzda alınan URL'yi kendi yönteminizle açan `openUrl` aksiyonu için bir işleyici uygulayın. :::info Capacitor SDK'da, bir URL'ye dokunulduğunda bu URL varsayılan olarak yerel tarayıcıda açılır: SDK, builder'da ayarladığınız **Open in** seçeneğini dikkate alarak `adapty.openWebUrl({ url, openIn })` fonksiyonunu çağırır ve flow'u açık tutar. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```typescript showLineNumbers const unsubscribe = await view.setEventHandlers({ onUrlPress(url) { // Open the URL your own way, e.g. with the Capacitor Browser plugin Browser.open({ url }); return false; // keep the flow open }, }); ``` ## Özel işlemleri yönetme \{#handle-custom-actions\} Başka işlemleri yürüten bir buton eklemek için: 1. Builder'da bir buton ekleyin, ona **Custom** işlemini atayın ve bir kimlik (ID) verin. 2. Uygulama kodunuzda, oluşturduğunuz işlem kimliği için bir işleyici (handler) uygulayın. Örneğin, farklı bir abonelik teklifleri setin ya da tek seferlik satın alımlarınız varsa, başka bir flow veya paywall gösterecek bir buton ekleyebilirsiniz: ```typescript showLineNumbers const unsubscribe = await view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another flow or paywall } }, }); ``` </SDKv4> <SDKv3> Adapty paywall builder kullanarak paywall oluşturuyorsanız, düğmeleri doğru şekilde ayarlamak önemlidir: 1. [Paywall builder'a bir düğme ekleyin](paywall-buttons) ve bu düğmeye mevcut bir action atayın ya da özel bir action ID oluşturun. 2. Atadığınız her action'ı işlemek için uygulamanıza kod yazın. Bu rehber, kodunuzda özel ve mevcut action'ları nasıl yöneteceğinizi göstermektedir. ## Paywallları kapatma \{#close-paywalls\} Paywallınızı kapatacak bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda, paywallı kapatan `close` eyleminin işleyicisini uygulayın. :::info Capacitor SDK'sında `close` eylemi, varsayılan olarak paywallı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywallı kapatmak başka bir paywallın açılmasını tetikleyebilir. ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { console.log('User closed paywall'); return true; // Allow the paywall to close } }); ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (ör. kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle butonlarla aynı şekilde işleyin. ::: Paywall'ınızdan bir bağlantı açan bir buton eklemek için (ör. **Terms of use** veya **Privacy policy**): 1. Paywall builder'da bir buton ekleyin, buna **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi bir tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info Capacitor SDK'da `window.open` eylemi varsayılan olarak URL'yi açar. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; // Don't close the paywall }, }); ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Login** aksiyonunu atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` aksiyonu için bir handler uygulayın. ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'login') { // Navigate to login screen console.log('User requested login'); } } }); ``` ## Özel işlemleri yönetme \{#handle-custom-actions\} Herhangi bir işlemi yöneten bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin, butona **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi setiniz veya tek seferlik satın almalarınız varsa, başka bir paywall görüntüleyen bir buton ekleyebilirsiniz: ```typescript showLineNumbers const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall } }, }); ``` </SDKv3> --- # File: capacitor-handling-events --- --- title: "Flow ve paywall olaylarını yönet - Capacitor" description: "Adapty'nin SDK'sı ile Capacitor uygulamanızda flow ve paywall olaylarını yönetin." --- <SDKv4> :::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve flow render etme gibi olayların işlenmesini kapsar. Ayrıca buton işlemlerini de (flow'u kapatma, bağlantı açma, özel eylemler vb.) ayarlayabilirsiniz. Ayrıntılar için [buton eylemlerini işleme kılavuzumuza](capacitor-handle-paywall-actions) bakın. ::: [Flow Builder](adapty-flow-builder) ile oluşturulan flow'lar ve paywalllar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar arasında düğme basmaları (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve flow üzerinde gerçekleştirilen satın alma ile ilgili işlemlere dair bildirimler yer alır. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızda flow ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `view.setEventHandlers` metodunu uygulayın: :::important Her olay için yalnızca bir handler belirleyebilirsiniz: `setEventHandlers`'ı birden fazla kez çağırmak, belirttiğiniz handler'ları geçersiz kılar ve hem varsayılan hem de daha önce ayarlanmış handler'ların yerini alır. Ayarlamadığınız handler'lar varsayılan davranışlarını korur. `setEventHandlers` bir unsubscribe fonksiyonu döndürür; `view.dismiss()` ise tüm handler'ları temizler. ::: ```typescript showLineNumbers const view = await createFlowView(flow); const unsubscribe = await view.setEventHandlers({ onCloseButtonPress() { return true; // close the flow (default behavior) }, onAndroidSystemBack() { return true; // close the flow; by default, it stays open }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type === 'success'; // close the flow on a successful purchase, keep it open for cancelled or pending purchases }, onPurchaseStarted(product) { /***/ }, onPurchaseFailed(error, product) { /***/ }, onRestoreCompleted(profile) { /***/ }, onRestoreFailed(error) { /***/ }, onProductSelected(productId) { /***/ }, onError(error) { /***/ }, onLoadingProductsFailed(error) { /***/ }, onUrlPress(url, openIn) { adapty.openWebUrl({ url, openIn }).catch(console.warn); // same as the SDK default return false; // keep the flow open }, onAppeared() { /***/ }, onDisappeared() { /***/ }, onWebPaymentNavigationFinished() { /***/ }, }); ``` <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> Aşağıdaki örnekler, her işleyicide kullanılabilen özellikleri ve açıklayıcı değerleri yorum olarak göstermektedir. ```typescript // onUrlPress url; // 'https://example.com/terms' openIn; // 'browser_in_app' or 'browser_out_app' // onCustomAction actionId; // 'login' // onProductSelected productId; // 'premium_monthly' // onPurchaseStarted, onPurchaseCompleted, onPurchaseFailed product.vendorProductId; // 'premium_monthly' product.localizedTitle; // 'Premium Monthly' product.localizedDescription; // 'Premium subscription for 1 month' product.price?.amount; // 9.99 product.price?.currencyCode; // 'USD' product.price?.localizedString; // '$9.99' // onPurchaseCompleted purchaseResult.type; // 'success', 'pending', or 'user_cancelled' if (purchaseResult.type === 'success') { purchaseResult.profile.accessLevels['premium']?.isActive; // true } // onRestoreCompleted profile.accessLevels['premium']?.isActive; // true // onPurchaseFailed, onRestoreFailed, onError, onLoadingProductsFailed error.message; // 'Purchase failed due to insufficient funds' ``` </Details> İhtiyaç duyduğunuz event handler'ları kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz. Bu sayede kullanılmayan event listener'lar oluşturulmaz. Zorunlu event handler yoktur. Event handler'lar bir boolean döndürür. `true` döndürülürse görüntüleme süreci tamamlanmış sayılır; böylece flow ekranı kapanır ve bu view için event listener'lar kaldırılır. Bazı olay işleyicilerinin geçersiz kılabileceğiniz varsayılan davranışları vardır: - `onCloseButtonPress`: Kapat düğmesine basıldığında flow'u kapatır. - `onUrlPress`: Tıklanan URL'yi, builder'da ayarlanan **Open in** seçeneğine uyarak `adapty.openWebUrl` aracılığıyla yerel tarayıcıda açar ve flow'u açık tutar. - `onAndroidSystemBack`: **Back** düğmesine basıldığında flow'u açık tutar. Kapatmak için `true` döndürün. - `onPurchaseCompleted`: Satın alma tamamlandıktan sonra flow'u açık tutar. Kapatmak için `true` döndürün. - `onRestoreCompleted`: Başarılı bir geri yüklemeden sonra flow'u açık tutar. Kapatmak için `true` döndürün. - `onError`: Render işlemi başarısız olursa flow'u kapatır. ### Olay yöneticileri \{#event-handlers\} | Olay işleyicisi | Açıklama | |:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | Kullanıcı özel bir eylem gerçekleştirdiğinde, örneğin bir [özel düğmeye](paywall-buttons) tıkladığında çağrılır. | | **onUrlPress** | Kullanıcı flow'unuzdaki bir URL'ye tıkladığında çağrılır. | | **onAndroidSystemBack** | Kullanıcı Android sistem **Back** düğmesine bastığında çağrılır. Flow varsayılan olarak açık kalır; kapatmak için `true` döndürün. | | **onCloseButtonPress** | Kapat düğmesi görünür durumdayken kullanıcı üzerine bastığında çağrılır. Bu işleyicide flow ekranını kapatmanız önerilir. | | **onPurchaseCompleted** | Satın alma tamamlandığında çağrılır; başarılı, kullanıcı tarafından iptal edilmiş veya onay bekliyor olabilir. Başarılı bir satın almada güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı iptalleri ve bekleyen ödemeler (ör. ebeveyn onayı gerekli) bu olayı tetikler, `onPurchaseFailed`'ı değil. | | **onPurchaseStarted** | Kullanıcı satın alma sürecini başlatmak için "Purchase" eylem düğmesine bastığında çağrılır. | | **onPurchaseFailed** | Satın alma hatalar nedeniyle başarısız olduğunda çağrılır (ör. ödeme kısıtlamaları, geçersiz ürünler, ağ hataları, işlem doğrulama hataları). Kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz; bunlar `onPurchaseCompleted`'ı tetikler. | | **onRestoreStarted** | Kullanıcı satın alma geri yükleme sürecini başlattığında çağrılır. | | **onRestoreCompleted** | Satın alma geri yükleme başarılı olduğunda çağrılır ve güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanız önerilir. Nasıl kontrol edileceğini öğrenmek için [Abonelik durumu](capacitor-listen-subscription-changes) konusuna bakın. | | **onRestoreFailed** | Geri yükleme işlemi başarısız olduğunda çağrılır ve `AdaptyError` sağlar. | | **onProductSelected** | Flow görünümünde herhangi bir ürün seçildiğinde çağrılır; satın alma öncesinde kullanıcının ne seçtiğini izlemenizi sağlar. | | **onError** | Görünüm oluşturma sırasında bir hata meydana geldiğinde çağrılır ve `AdaptyError` sağlar. Bu tür hatalar gerçekleşmemelidir; bir taneyle karşılaşırsanız lütfen bize bildirin. | | **onLoadingProductsFailed** | Ürün yükleme başarısız olduğunda çağrılır ve `AdaptyError` sağlar. Görünüm oluşturmada `prefetchProducts: true` ayarlamadıysanız AdaptyUI gerekli nesneleri sunucudan kendisi alır. | | **onAppeared** | Flow kullanıcıya gösterildiğinde çağrılır. iOS'ta, kullanıcı flow içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) bastığında ve bir web paywall uygulama içi tarayıcıda açıldığında da çağrılır. | | **onDisappeared** | Flow kullanıcı tarafından kapatıldığında çağrılır. iOS'ta, uygulama içi tarayıcıda bir flow'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda da çağrılır. | | **onWebPaymentNavigationFinished** | Satın alma için bir [web paywall](web-paywall) açılmaya çalışıldıktan sonra çağrılır; başarılı veya başarısız olmasından bağımsız olarak. | | **onRequestAppReview** | Flow'dan gelen uygulama değerlendirme istekleri için ayrılmıştır. Flow'lar henüz uygulama değerlendirme isteği tetiklemiyor, bu yüzden uygulamanız gerekmez. | | **onAnalytics** | Flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmiyor, bu yüzden uygulamanız gerekmez. | | **onRequestPermission** | Flow'dan gelen sistem izin istekleri (bildirimler veya kamera erişimi gibi) için ayrılmıştır. Flow'lar henüz izin isteği tetiklemiyor, bu yüzden uygulamanız gerekmez. | | **onObserverPurchaseInitiated** | Yalnızca gözlemci mod: Kullanıcı flow'da satın alma düğmesine bastığında çağrılır. Adapty satın almayı gerçekleştirmez — kendi satın alma kodunuzla yapın, ardından işlemi Adapty'ye bildirin. Aşağıdaki [Gözlemci modunda satın almaları yönetme](#handle-purchases-in-observer-mode) bölümüne bakın. | | **onObserverRestoreInitiated** | Yalnızca gözlemci mod: Kullanıcı flow'da geri yükleme düğmesine bastığında çağrılır. Adapty geri yükleme yapmaz — kendiniz yapın, ardından geri yüklenen işlemleri bildirin. Aşağıdaki [Gözlemci modunda satın almaları yönetme](#handle-purchases-in-observer-mode) bölümüne bakın. | ### Observer mode'da satın alma işlemlerini yönetme \{#handle-purchases-in-observer-mode\} SDK'yı [Observer mode](implement-observer-mode-capacitor) (`observerMode: true`) ile etkinleştirdiyseniz ve Adapty tarafından oluşturulan bir flow sunuyorsanız, SDK satın alma işlemlerini sizin yerinize gerçekleştirmez. Kullanıcı satın alma veya geri yükleme düğmesine dokunduğunda SDK, `onObserverPurchaseInitiated` veya `onObserverRestoreInitiated` metodunu çağırır; böylece satın alma veya geri yükleme işlemini kendi kodunuzla gerçekleştirebilirsiniz. Tam kurulum için [Observer mode'da flow'ları sunma](capacitor-present-flows-in-observer-mode) konusuna bakın. </SDKv4> <SDKv3> :::important Bu kılavuz, satın alımlar, geri yüklemeler, ürün seçimi ve paywall oluşturma için olay işlemeyi kapsar. Ayrıca düğme işlemeyi de (paywall kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini işleme kılavuzumuza](capacitor-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış paywalllar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamalarını (kapat butonları, URL'ler, ürün seçimleri vb.) ve paywallda gerçekleştirilen satın alma işlemlerine ilişkin bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `view.setEventHandlers` metodunu uygulayın: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { console.log('User closed paywall'); return true; // Allow the paywall to close }, onAndroidSystemBack() { console.log('User pressed back button'); return true; // Allow the paywall to close }, onAppeared() { console.log('Paywall appeared'); return false; // Don't close the paywall }, onDisappeared() { console.log('Paywall disappeared'); }, onPurchaseCompleted(purchaseResult, product) { console.log('Purchase completed:', purchaseResult); return purchaseResult.type !== 'user_cancelled'; // Close if not cancelled }, onPurchaseStarted(product) { console.log('Purchase started:', product); return false; // Don't close the paywall }, onPurchaseFailed(error, product) { console.error('Purchase failed:', error); return false; // Don't close the paywall }, onRestoreCompleted(profile) { console.log('Restore completed:', profile); return true; // Close the paywall after successful restore }, onRestoreFailed(error) { console.error('Restore failed:', error); return false; // Don't close the paywall }, onProductSelected(productId) { console.log('Product selected:', productId); return false; // Don't close the paywall }, onRenderingFailed(error) { console.error('Rendering failed:', error); return false; // Don't close the paywall }, onLoadingProductsFailed(error) { console.error('Loading products failed:', error); return false; // Don't close the paywall }, onUrlPress(url) { window.open(url, '_blank'); return false; // Don't close the paywall }, }); ``` <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> ```typescript // onCloseButtonPress { "event": "close_button_press" } // onAndroidSystemBack { "event": "android_system_back" } // onAppeared { "event": "paywall_shown" } // onDisappeared { "event": "paywall_closed" } // onUrlPress { "event": "url_press", "url": "https://example.com/terms" } // onCustomAction { "event": "custom_action", "actionId": "login" } // onProductSelected { "event": "product_selected", "productId": "premium_monthly" } // onPurchaseStarted { "event": "purchase_started", "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Success { "event": "purchase_completed", "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Cancelled { "event": "purchase_completed", "purchaseResult": { "type": "user_cancelled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseFailed { "event": "purchase_failed", "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } // onRestoreCompleted { "event": "restore_completed", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } // onRestoreFailed { "event": "restore_failed", "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } // onRenderingFailed { "event": "rendering_failed", "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } // onLoadingProductsFailed { "event": "loading_products_failed", "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> İhtiyaç duyduğunuz event handler'ları kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz. Bu sayede kullanılmayan event listener'lar oluşturulmaz. Zorunlu event handler yoktur. Event handler'lar bir boolean döndürür. `true` döndürülürse, gösterim süreci tamamlanmış sayılır; böylece paywall ekranı kapanır ve bu view için event listener'lar kaldırılır. Bazı event handler'ların, gerekirse geçersiz kılabileceğiniz varsayılan davranışları vardır: - `onCloseButtonPress`: Kapat düğmesine basıldığında paywall'ı kapatır. - `onAndroidSystemBack`: **Geri** düğmesine basıldığında paywall'ı kapatır. - `onRestoreCompleted`: Başarılı bir restore işleminin ardından paywall'ı kapatır. - `onPurchaseCompleted`: Kullanıcı iptal etmedikçe paywall'ı kapatır. - `onRenderingFailed`: Paywall oluşturma başarısız olursa paywall'ı kapatır. - `onUrlPress`: URL'leri sistem tarayıcısında açar ve paywall'ı açık tutar. ### Olay işleyicileri \{#event-handlers\} | Olay yöneticisi | Açıklama | |:----------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | Kullanıcı özel bir eylem gerçekleştirdiğinde, örneğin bir [özel düğmeye](paywall-buttons) tıkladığında çağrılır. | | **onUrlPress** | Kullanıcı paywall'ınızdaki bir URL'ye tıkladığında çağrılır. | | **onAndroidSystemBack** | Kullanıcı Android sistem **Geri** düğmesine dokunduğunda çağrılır. | | **onCloseButtonPress** | Kapat düğmesi görünür durumdayken kullanıcı ona dokunduğunda çağrılır. Bu yöneticide paywall ekranını kapatmanız önerilir. | | **onPurchaseCompleted** | Satın alma tamamlandığında, ister başarılı olsun ister kullanıcı tarafından iptal edilmiş ya da onay bekleniyor olsun çağrılır. Başarılı satın almalarda güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı iptalleri ve bekleyen ödemeler (örneğin ebeveyn onayı gerekli) `onPurchaseFailed` değil bu olayı tetikler. | | **onPurchaseStarted** | Kullanıcı satın alma işlemini başlatmak için "Satın Al" eylem düğmesine dokunduğunda çağrılır. | | **onPurchaseCancelled** | Kullanıcı satın alma işlemini başlatıp manuel olarak kesintiye uğrattığında (ödeme diyaloğunu iptal ettiğinde) çağrılır. | | **onPurchaseFailed** | Satın alma hatalar nedeniyle başarısız olduğunda (örneğin ödeme kısıtlamaları, geçersiz ürünler, ağ hataları, işlem doğrulama hataları) çağrılır. Kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz; bunlar `onPurchaseCompleted`'ı tetikler. | | **onRestoreStarted** | Kullanıcı satın alma geri yükleme işlemini başlattığında çağrılır. | | **onRestoreCompleted** | Satın alma geri yükleme başarılı olduğunda çağrılır ve güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanız önerilir. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](capacitor-listen-subscription-changes) konusuna bakın. | | **onRestoreFailed** | Geri yükleme işlemi başarısız olduğunda çağrılır ve `AdaptyError` sağlar. | | **onProductSelected** | Paywall görünümündeki herhangi bir ürün seçildiğinde çağrılır; satın alma öncesinde kullanıcının ne seçtiğini izlemenizi sağlar. | | **onAppeared** | Paywall görünümü ekranda belirdiğinde çağrılır. iOS'ta, kullanıcı paywall içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve uygulama içi tarayıcıda bir web paywall açıldığında da çağrılır. | | **onDisappeared** | Paywall görünümü ekrandan kaybolduğunda çağrılır. iOS'ta, uygulama içi tarayıcıda bir paywall'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda da çağrılır. | | **onRenderingFailed** | Görünüm oluşturma sırasında hata oluştuğunda çağrılır ve `AdaptyError` sağlar. Bu tür hatalar yaşanmamalıdır; yaşanırsa lütfen bize bildirin. | | **onLoadingProductsFailed** | Ürün yükleme başarısız olduğunda çağrılır ve `AdaptyError` sağlar. Görünüm oluşturma sırasında `prefetchProducts: true` ayarlamadıysanız AdaptyUI gerekli nesneleri sunucudan kendisi alacaktır. | </SDKv3> --- # File: capacitor-use-fallback-paywalls --- --- title: "Capacitor - Yedek paywall kullanımı" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucularına erişilemediğinde durumu ele alın" --- Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} ### Android \{#android\} 1. Yedek yapılandırma dosyasını uygulamanıza ekleyin. Aşağıdaki dizinlerden birini seçin: * **android/app/src/main/assets/** * **android/app/src/main/res/raw/** Not: `res/raw` klasörü özel bir dosya adlandırma kuralına sahiptir (harf ile başlamalı, büyük harf kullanılmamalı, alt çizgi dışında özel karakter kullanılmamalı ve isimde boşluk olmamalı). 2. `FileLocation` sabitinin `android` özelliğini güncelleyin: * Dosya `assets` dizinindeyse, dizine göre dosyanın göreli yolunu girin. * Dosya `res/raw` dizinindeyse, dosyanın uzantısız adını girin. ### iOS \{#ios\} 1. Yedek JSON dosyasını proje paketinize ekleyin: XCode'da **File** menüsünü açın ve **Add Files to "YourProjectName"** seçeneğini seçin. 2. Yapılandırma dosyanızın adını `FileLocation` sabitinin `ios` özelliğine aktarın. ## Örnek \{#example\} ```typescript showLineNumbers const fileLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } }; await adapty.setFallback({ fileLocation }); ``` :::important `setFallback`, SDK hedef flow, paywall veya onboarding'i getirmeden önce çalıştırılmalıdır. ::: Parametreler: | Parametre | Açıklama | | :------------------- | :------------------------------------------------------- | | **fileLocation** | Yedek yapılandırma dosyasının konumunu temsil eden nesne. | --- # File: capacitor-localizations-and-locale-codes --- --- title: "Capacitor SDK'da yerelleştirme ve yerel ayar kodlarını kullanma" description: "Adapty SDK ile Capacitor uygulamanızdaki paywallları nasıl yerelleştireceğinizi öğrenin." --- <SDKv4> ## Bu neden önemlidir \{#why-this-is-important\} Adapty bir flow için lokalizasyonu seçerken ve özel bir paywall için remote config okurken locale kodları devreye girer. Locale kodları karmaşık olabilir ve platformdan platforma farklılık gösterebilir; bu nedenle Adapty, desteklediği her platformda tek bir iç standarda dayanır. Bu standardı anlamak, kullanıcının hangi lokalizasyonu alacağını tahmin etmenize yardımcı olur. ## Adapty'de kullanılan yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, küçük harfli alt etiketlerden oluşur ve bunlar kısa çizgilerle ayrılır. Birkaç örnek: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, bir kullanıcının yerel ayarıyla eşleşen lokalizasyonu ararken şu adımlar izlenir: 1. Yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgiyle (`-`) değiştirilir 2. Adapty, tam olarak eşleşen yerel ayar koduna sahip lokalizasyonu arar 3. Eşleşme bulunamazsa, Adapty ilk kısa çizgiden önceki alt dizeyi alır (`pt-br` için `pt`) ve eşleşen lokalizasyonu arar 4. Yine eşleşme bulunamazsa, Adapty varsayılan `en` lokalizasyonunu döndürür Bu sayede `'pt_BR'`, `pt-BR` ve `pt-br` ifadelerinin hepsi aynı lokalizasyona karşılık gelir. ## Lokalizasyonları uygulama \{#implementing-localizations\} SDK v4'te bir flow çekerken locale kodu geçmenize gerek yok. - **Flow Builder ve Paywall Builder paywallları**: Adapty, lokalizasyonu cihaz dilinden ve builder'da yapılandırdığınız lokalizasyonlardan otomatik olarak çözer. Flow'u `createFlowView` ile render edin — locale koduna gerek yok. - **Özel (remote config) paywalllar**: `getFlow`, yapılandırılmış tüm lokalizasyonları `flow.remoteConfigs` içinde döndürür. Her girdinin bir `lang` kodu ve bir `data` nesnesi vardır. Kendi yedek mantığınızla kullanıcıya uyan girdiyi seçin: ```typescript showLineNumbers const flow = await adapty.getFlow({ placementId: 'placement_id' }); const config = flow.remoteConfigs?.find((c) => c.lang === 'en') ?? flow.remoteConfigs?.[0]; // read your values from config?.data ``` Yukarıdaki yerel ayar kodu eşleştirme kuralları, Adapty'nin her remote config üzerinde saklanan `lang` kodlarını nasıl normalleştirdiğini açıklar. </SDKv4> <SDKv3> ## Bu neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır — örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywall'u getirmeye çalıştığınızda. Yerel ayar kodları karmaşık bir yapıya sahiptir ve platformdan platforma farklılık gösterebilir; bu nedenle desteklediğimiz tüm platformlar için dahili bir standart kullanıyoruz. Ancak bu kodlar karmaşık olduğundan, sunucumuza ne gönderdiğinizi ve ardından ne olduğunu tam olarak anlamanız son derece önemlidir; böylece her zaman beklediğinizi alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Birkaç örnek: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan yerel ayar koduyla birlikte bir çağrı aldığında ve paywall'ın ilgili yerelleştirmesini aramaya başladığında şu adımlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgiyle (`-`) değiştirilir 2. Ardından tam olarak eşleşen yerel ayar koduna sahip yerelleştirme aranır 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır 4. Yine eşleşme bulunamazsa varsayılan `en` yerelleştirmesi döndürülür Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri Uygulama: Önerilen Yol \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, muhtemelen projenizde zaten yerelleştirilmiş string dosyalarıyla çalışıyorsunuzdur. Bu durumda, ilgili yerelleştirmeler için her dosyaya Adapty yerel ayar kodu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde alın: ```javascript showLineNumbers // 1. Modify your localization files (e.g., using react-i18next) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Extract and use the locale code const MyComponent = () => { const { t } = useTranslation(); const fetchPaywall = async () => { const locale = t('adapty_paywalls_locale'); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; }; ``` Bu sayede uygulamanızın her kullanıcısı için hangi yerelleştirmenin alınacağını tam olarak kontrol edebilirsiniz. ## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça yerel ayar kodu tanımlamadan da benzer (ancak özdeş olmayan) sonuçlar elde edebilirsiniz. Bu yaklaşımda, platformunuzun sağladığı başka nesnelerden yerel ayar kodu çıkarmak gerekir; örneğin: ```javascript showLineNumbers const getLocaleCode = () => { if (Capacitor.getPlatform() === 'ios') { return navigator.language || 'en'; } else { return navigator.language || 'en'; } }; const fetchPaywall = async () => { const locale = getLocaleCode(); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; ``` Bu yaklaşımı birkaç nedenden dolayı önermiyoruz: 1. iOS'ta tercih edilen diller ile mevcut locale aynı değildir. Yerelleştirmenin doğru seçilmesini istiyorsanız, Apple'ın mantığına güvenmeniz gerekir; bu mantık, yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda kutudan çıktığı gibi çalışır. Alternatif olarak bu mantığı kendiniz de yeniden oluşturabilirsiniz. 2. Adapty sunucusunun tam olarak ne alacağını tahmin etmek güçtür. Örneğin iOS'ta bir cihazda `ar_OM@numbers='latn'` gibi bir locale elde edip bunu sunucumuza gönderebilirsiniz. Bu durumda aradığınız `ar-om` yerelleştirmesini değil, büyük ihtimalle beklenmedik olan `ar` yerelleştirmesini alırsınız. Yine de bu yaklaşımı kullanmaya karar verirseniz, ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun. </SDKv3> --- # File: capacitor-web-paywall --- --- title: "Web paywall'ları uygulama" description: "Adapty SDK ile Capacitor uygulamanızda web paywall'larını nasıl uygulayacağınızı öğrenin." --- :::important Başlamadan önce [kontrol panelinde web paywall'ınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya daha yeni bir sürümü yüklediğinizden emin olun. ::: ## Web paywall'ları açma \{#open-web-paywalls\} Kendiniz geliştirdiğiniz bir paywall üzerinde çalışıyorsanız, web paywall'larını SDK metoduyla yönetmeniz gerekir. `.openWebPaywall` metodu: 1. Belirli bir kullanıcıya gösterilen paywall'ı yönlendirildikleri web sayfasıyla ilişkilendirmek için Adapty'nin kullanacağı benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman geri döndüğünü takip eder ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` çağrısı yapar. Bu sayede ödeme başarılı olur ve erişim hakları güncellenirse, abonelik uygulamada neredeyse anında aktive edilir. ```typescript showLineNumbers try { await adapty.openWebPaywall({ paywallOrProduct: product }); } catch (error) { console.error('Failed to open web paywall:', error); } ``` :::note `openWebPaywall` metodunun iki versiyonu vardır: 1. `openWebPaywall({ paywallOrProduct: product })` — paywall'a göre URL'ler oluşturur ve URL'lere ürün verilerini de ekler. 2. `openWebPaywall({ paywallOrProduct: paywall })` — paywall'a göre URL'ler oluşturur ancak URL'lere ürün verilerini eklemez. Adapty paywall'ınızdaki ürünler web paywall'ındakilerden farklıysa bunu kullanın. SDK v4'te `paywallOrProduct`'ın paywall tarafı, bir `AdaptyFlowPaywall` alır — bu, alınan flow'un paywall varyasyonudur. İndeksleme yapmadan önce `flow.paywalls`'ın boş olmadığını kontrol edin; örneğin `flow.paywalls[0]`. ::: #### Hataları ele al \{#handle-errors\} | Hata | Açıklama | Önerilen eylem | |-----------------------------------------|----------------------------------------------------------------|---------------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Paywall için web satın alma URL'si yapılandırılmamış | Paywall'ın Adapty Kontrol Paneli'nde doğru yapılandırılıp yapılandırılmadığını kontrol edin | | AdaptyError.productWithoutPurchaseUrl | Ürün için web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın | | AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun | | AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler düzgün kodlanamadı | URL parametrelerinin geçerli ve doğru biçimlendirilmiş olduğunu doğrulayın | ## Web paywall URL'sini açmadan alma \{#get-the-web-paywall-url-without-opening-it\} Web satın alma sayfasını SDK'nın açmasını beklemek yerine kendiniz sunmak istiyorsanız `createWebPaywallUrl` kullanabilirsiniz. Bu fonksiyon, `openWebPaywall`'ın açacağı benzersiz URL'yi döndürür; bu sayede URL'yi kendi web view'ınızda gösterebilir veya yönlendirmeyi kendi koşullarınıza göre yönetebilirsiniz. Aynı `paywallOrProduct` argümanını kabul eder — bu, getirilmiş flow'un bir paywall varyantı (`AdaptyFlowPaywall`) veya bir `AdaptyPaywallProduct` olabilir. ```typescript showLineNumbers try { const url = await adapty.createWebPaywallUrl({ paywallOrProduct: product }); // open `url` in your own web view, or handle the redirect yourself } catch (error) { console.error('Failed to create web paywall URL:', error); } ``` :::note Bir flow'un butonundan herhangi bir URL'yi (web paywall değil) yerel tarayıcı üzerinden açmak için bunun yerine [`adapty.openWebUrl`](capacitor-handle-paywall-actions#open-urls-from-flows-and-paywalls) kullanın. ::: ## Web paywall'ları uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywall'ları uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Web paywall'lar varsayılan olarak harici tarayıcıda açılır. Kullanıcı deneyimini kesintisiz hale getirmek için web paywall'ları uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanızın içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `openWebPaywall` içinde `openIn` değerini `WebPresentation.BrowserInApp` olarak ayarlayın: ```typescript showLineNumbers try { await adapty.openWebPaywall({ paywallOrProduct: product, openIn: WebPresentation.BrowserInApp, // default – WebPresentation.BrowserOutApp }); } catch (error) { console.error('Failed to open web paywall:', error); } ``` --- # File: capacitor-present-flows-in-observer-mode --- --- title: "Capacitor SDK'da Observer modunda flow sunma" description: "Kendi kodunuzla satın almaları yönetirken Capacitor uygulamanızda Observer modunda flow'ları ve Paywall Builder paywall'larını sunun." --- Builder ile bir flow veya paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir flow veya paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız [Display flows & paywalls](capacitor-present-paywalls) konusuna bakın. ::: :::info Bu özellik, Adapty Capacitor SDK 4.0 veya sonraki sürümlerini gerektirir; daha önce yalnızca yerel iOS ve Android SDK'larında kullanılabilirdi. Yükseltmek için [geçiş kılavuzuna](migration-to-capacitor-sdk-v4) bakın. ::: <details> <summary>Flow sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'nin [App Store ile](initial_ios) ve [Google Play ile](initial-android) ilk entegrasyonunu ayarlayın. 2. Adapty SDK'yı yükleyin ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. [Capacitor SDK kurulum kılavuzuna](sdk-installation-capacitor#activate-adapty-module-of-adapty-sdk) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builderlarda flow'lar veya paywalllar yapılandırın](create-paywall) ve ürünleri bunlara atayın. 5. [Placementlar oluşturun ve flow'larınızı veya paywalllarınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını alın](capacitor-get-pb-paywalls). </details> Observer modunda SDK, satın alma işlemlerini sizin adınıza gerçekleştirmez. Bir kullanıcı, Adapty tarafından render edilen bir flow veya paywallda satın alma ya da geri yükleme düğmesine dokunduğunda, SDK doğrudan satın alma veya geri yükleme yapmak yerine `onObserverPurchaseInitiated` veya `onObserverRestoreInitiated` olay işleyicinizi çağırır — satın alma veya geri yükleme işlemini orada kendi kodunuzla gerçekleştirin. 1. View üzerindeki observer modu olay işleyicilerini ayarlayın. Diğer platformlardan farklı olarak, ayrı bir resolver nesnesi yoktur — işleyiciler, normal [olay işleyicilerinin](capacitor-handling-events) bir parçasıdır; bu nedenle oluşturduğunuz her view'da bunları ayarlayın: ```typescript showLineNumbers title="Capacitor" import { adapty, createFlowView } from '@adapty/capacitor'; const view = await createFlowView(flow); const unsubscribe = await view.setEventHandlers({ onObserverPurchaseInitiated(product, onStartPurchase, onFinishPurchase) { onStartPurchase(); // the view shows its loading indicator myPurchaseApi(product.vendorProductId) .then((transactionId) => adapty.reportTransaction({ transactionId, variationId: flow.variationId }), ) .finally(() => onFinishPurchase()); // the view hides the loading indicator return false; // keep the flow open; dismiss it yourself after success }, onObserverRestoreInitiated(onStartRestore, onFinishRestore) { onStartRestore(); myRestoreApi().finally(() => onFinishRestore()); return false; }, }); ``` `onObserverPurchaseInitiated` handler, kullanıcının bir satın alma başlattığını bildirir; `onObserverRestoreInitiated` ise kullanıcının bir geri yükleme başlattığını. Bu olaylara yanıt olarak kendi özel satın alma veya geri yükleme flow'unuzu tetikleyin. Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'a bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi düzgün flow davranışı için gereklidir: | Callback | Description | | :----------------- | :------------------------------------------------------------------------------- | | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | 2. Flow görünümünü her zamanki gibi sunun: [flow'u alın ve görünümünü oluşturun](capacitor-get-pb-paywalls), ardından [sunun](capacitor-present-paywalls). Ekstra parametre gerekmez — handler'lar yalnızca SDK `observerMode: true` ile etkinleştirildiğinde tetiklenir. :::warning [İşlemi bildirmeyi ve paywall ile ilişkilendirmeyi](report-transactions-observer-mode-capacitor) unutmayın. Aksi takdirde Adapty işlemi tanımaz ve satın almanın hangi paywall'dan geldiğini belirleyemez. ::: --- # File: capacitor-implement-paywalls-manually --- --- title: "Paywallları manuel olarak uygulama" description: "Adapty SDK ile Capacitor uygulamanızda paywallları manuel olarak nasıl uygulayacağınızı öğrenin." --- ## Satın alma işlemlerini kabul etme \{#accept-purchases\} Kendinizin uyguladığı paywalllarla çalışıyorsanız, `makePurchase` metodunu kullanarak satın alma işlemlerini Adapty'ye devredebilirsiniz. Bu sayede tüm kullanıcı senaryolarını biz yönetiriz; sizin yalnızca satın alma sonuçlarını ele almanız yeterlidir. :::important `makePurchase`, Adapty Kontrol Paneli'nde oluşturulmuş ürünlerle çalışır. [Hızlı başlangıç kılavuzunu](quickstart) takip ederek ürünleri ve bunları almaya yönelik yöntemleri kontrol panelinde yapılandırdığınızdan emin olun. ::: <CustomDocCardList ids={['capacitor-quickstart-manual', 'fetch-paywalls-and-products-capacitor', 'present-remote-config-paywalls-capacitor', 'capacitor-making-purchases', 'capacitor-restore-purchase']} /> ## Gözlemci modu \{#observer-mode\} Satın alma işleme mantığınızı sıfırdan kendiniz uygulamak istiyor ancak Adapty'nin gelişmiş analizlerinden yararlanmaya devam etmek istiyorsanız gözlemci modunu kullanabilirsiniz. :::important Gözlemci modunun sınırlamalarını [buradan](observer-vs-full-mode) inceleyebilirsiniz. ::: <CustomDocCardList ids={['implement-observer-mode-capacitor', 'report-transactions-observer-mode-capacitor']} /> --- # File: capacitor-quickstart-manual --- --- title: "Capacitor SDK'da özel paywall'unuzda satın almaları etkinleştirin" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Capacitor paywall'larınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywalllarınıza nasıl entegre edeceğinizi açıklar. Adapty SDK ürünleri getirirken, yeni satın almaları işlerken ve önceki satın almaları geri yüklerken paywall uygulaması üzerinde tam kontrol sizde kalır. Bu kılavuz, Adapty Capacitor SDK v4 API'lerini kullanır — v3 kullanıyorsanız, ilgili metod adları için [migration kılavuzuna](migration-to-capacitor-sdk-v4) bakın. :::important **Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın almaları etkinleştirmenin en kolay yolunu istiyorsanız [Adapty Paywall Builder](capacitor-quickstart-paywalls)'ı kullanın. Paywall Builder ile paywallları kod yazmadan görsel bir editörde oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlayın \{#set-up-products\} Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalls**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywall'lar aracılığıyla ulaşılır; bu tasarım sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. SDK v4'te bir placement için paywall varyantları bir **flow** nesnesi tarafından taşınır — bir flow çekip ürünlerini sorgularsınız. - [**Placement'lar**](placements) – uygulamanızda paywall'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Kontrol panelinde placement'lar için paywall'lar ayarlarsınız, ardından kodunuzda placement ID'si ile bunları talep edersiniz. Bu yapı A/B testi yapmayı ve farklı kullanıcılara farklı paywall'lar göstermeyi kolaylaştırır. Özel paywall kullanıyor olsanız bile bu kavramları anladığınızdan emin olun. Temel olarak bunlar, uygulamanızda sattığınız ürünleri yönetme yönteminizdir. Özel paywallınızı uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu kurulum, ürünlerinizi almanıza olanak tanır. Kontrol panelinde ne yapmanız gerektiğini anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetin \{#manage-users\} Kendi tarafınızda backend kimlik doğrulamasıyla veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve tanımlanmış kullanıcıları farklı şekilde ele alır. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik belirleme hızlı başlangıç kılavuzunu](capacitor-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywall'ınız için ürünleri almak üzere şunları yapmanız gerekir: 1. [placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın. 2. Bu flow için ürünler dizisini `getPaywallProducts` metodunu kullanarak alın. ```typescript showLineNumbers async function loadPaywall() { try { const flow: AdaptyFlow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts({ flow }); // Use products to build your custom paywall UI } catch (error) { // Handle the error } } ``` ## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\} Kullanıcı özel paywallınızda bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```typescript showLineNumbers async function purchaseProduct(product: AdaptyPaywallProduct) { try { const result: AdaptyPurchaseResult = await adapty.makePurchase({ product }); if (result.type === 'success') { // Purchase successful, profile updated } else if (result.type === 'user_cancelled') { // User canceled the purchase } else if (result.type === 'pending') { // Purchase is pending (e.g., user will pay offline with cash) } } catch (error) { // Handle the error } } ``` ## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik içeren tüm uygulamaların kullanıcıların satın almalarını geri yükleyebileceği bir yol sunmasını şart koşar. Kullanıcı geri yükleme düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```typescript showLineNumbers async function restorePurchases() { try { const profile: AdaptyProfile = await adapty.restorePurchases(); // Restore successful, profile updated } catch (error) { // Handle the error } } ``` ## 4. Adım. Abonelik durumunu kontrol edin \{#step-4-check-the-subscription-status\} Bir satın alma veya geri yükleme işleminin ardından, paywall gösterip göstermeyeceğinize ya da ücretli özellikleri açıp açmayacağınıza karar vermek için kullanıcının [access level](access-level) durumunu kontrol edin. `makePurchase` ve `restorePurchases` metotları güncellenmiş profili zaten döndürür; uygulamanın başka bir yerinde mevcut duruma ihtiyaç duyduğunuzda `getProfile` metodunu kullanın: ```typescript showLineNumbers async function hasPremiumAccess(): Promise<boolean> { try { const profile = await adapty.getProfile(); return profile.accessLevels?.['premium']?.isActive ?? false; } catch (error) { // Handle the error } return false; } ``` Abonelik durumunu kontrol etmenin ve gerçek zamanlı güncellemeleri dinlemek dahil izlemenin daha fazla yolu için bkz. [Abonelik durumunu kontrol etme](capacitor-check-subscription-status). ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada gösterilmeye hazır. Paywall üzerinden test satın alımı tamamlayabildiğinizi doğrulamak için [App Store sandbox](test-purchases-in-sandbox) veya [Google Play Store](testing-on-android) ortamında satın alımlarınızı test edin. Prodüksiyon ortamına hazır bir uygulamanın nasıl göründüğünü görmek için örnek uygulamamızdaki [App.tsx](https://github.com/adaptyteam/AdaptySDK-Capacitor/blob/master/examples/adapty-devtools/src/screens/app/App.tsx) dosyasına göz atın; bu dosyada hata yönetimi, yükleme durumları ve kapsamlı SDK entegrasyonuyla birlikte satın alma işlemleri gösterilmektedir. --- # File: fetch-paywalls-and-products-capacitor --- --- title: "Capacitor SDK'da remote config paywallları için paywallları ve ürünleri getir" description: "Kullanıcı monetizasyonunu artırmak için Adapty Capacitor SDK'da paywallları ve ürünleri getirin." --- <SDKv4> Remote config ve custom paywall bilgilerini göstermeden önce bunları fetch etmeniz gerekir. Bu konunun remote config ve custom paywall'larla ilgili olduğunu lütfen unutmayın. Flow veya **Flow Builder** ya da **Paywall Builder** ile özelleştirilmiş paywall'ları fetch etme konusunda rehberlik için [Flow Builder flow'larını ve Paywall Builder paywall'larını ve yapılandırmalarını fetch etme](capacitor-get-pb-paywalls) bölümüne bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları ve ürünleri fetch etmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. [Ürünlerinizi oluşturun](create-product) (Adapty Kontrol Paneli'nde). 2. [Bir flow veya paywall oluşturun ve ürünleri ekleyin](create-paywall) (Adapty Kontrol Paneli'nde). 3. [Placement'lar oluşturun ve flow ya da paywall'ı placement'a ekleyin](create-placement) (Adapty Kontrol Paneli'nde). 4. [Adapty SDK'yı yükleyin](sdk-installation-capacitor) (mobil uygulamanıza). </details> ## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin birleşimidir. Bu platformlar arası ürünler, belirli mobil uygulama placement'larında sergilemenizi sağlamak amacıyla flow'lara ve paywall'lara entegre edilir. Ürünleri görüntülemek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan koda yazmanız gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir flow bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```typescript showLineNumbers try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); // the requested flow } catch (error) { console.error('Failed to fetch flow:', error); } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar düzensiz olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak amacıyla oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında sıfırlandığını unutmayın.</p><p></p><p>Adapty SDK, flow'ları ve paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](capacitor-use-fallback-paywalls). Flow'ları ve paywall'ları daha hızlı getirmek için CDN, CDN'e ulaşılamadığında ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken flow'larınızın her zaman en güncel sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **params.loadTimeoutMs** | <p>isteğe bağlı</p><p>varsayılan: 5000 ms</p> | <p>Bu değer, metodun zaman aşımı süresini (milisaniye cinsinden) sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeoutMs` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | :::note v4'te `getFlow` artık `locale` parametresi almıyor. Özel paywalllar için mevcut tüm locale'ler, flow'un remote config'inde (`flow.remoteConfigs`) döndürülür; kullanıcının cihazına veya uygulama ayarına uyan olanı seçin. ::: Ürün ID'lerini kod içine sabit olarak yazmayın! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Tek sabit olarak yazmanız gereken şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, paywall varyasyonları (`paywalls`) ve yapılandırılmış her yerel ayar için bir giriş içeren `remoteConfigs` dizisini barındıran bir `AdaptyFlow` nesnesi. Flow için ürünleri getirmek üzere `getPaywallProducts({ flow })` çağrısını kullanın. | ## Ürünleri getir \{#fetch-products\} Flow'u aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ flow }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) nesnesindeki bu özelliklere erişmeniz gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler için bağlantılı dokümana bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirme, cihazın yerel ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapılır. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price?.localizedString` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Fiyata sayısal olarak erişmek için `product.price?.amount` kullanabilirsiniz. Değer yerel para biriminde sunulur. İlgili para birimi sembolünü almak için `product.price?.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (ör. hafta, ay, yıl vb.) göstermek için `product.subscription?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscription?.subscriptionPeriod` kullanın. Buradan `unit` özelliğine erişerek uzunluğu (yani 'day', 'week', 'month', 'year' veya 'unknown') alabilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelikte `unit` özelliğinde `'month'`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini rozet veya başka bir gösterge ile belirtmek için `product.subscription?.offer?.phases` özelliğine bakın. Bu, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilen bir listedir. Her aşama nesnesi şu kullanışlı özellikleri içerir:<br/>• `paymentMode`: `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` ve `'unknown'` değerlerini alabilen bir dize. Ücretsiz denemeler `'free_trial'` türünde olur.<br/>• `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarına göre açıklayan yerelleştirilmiş bir dize. Örneğin üç günlük bir deneme teklifi bu alanda `'3 days'` olarak görünür.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarına bu özellik aracılığıyla ulaşabilirsiniz. Teklifler için önceki bölümde açıklanan yöntemle aynı şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim abonelik dönemi. | ## Varsayılan kitle flow'u ile flow getirme işlemini hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve placement'ınız olduğu ve kullanıcılarınızın zayıf bir internet bağlantısına sahip olduğu durumlarda, bir flow'u getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow'u getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu bilmek önemlidir: önerilen yaklaşım, yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-capacitor#fetch-flow-information) bölümünde açıklandığı gibi `getFlow` metoduyla flow'u getirmektir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecekteki) farklı flow'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görür; bu da ülkelere, marketing attribution'a veya kendi özel niteliklerinize göre kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Eğer daha hızlı flow çekme işleminden yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-capacitor#fetch-flow-information) açıklanan `getFlow` yöntemini kullanmaya devam edin. ::: ```typescript showLineNumbers try { const flow = await adapty.getFlowForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', params: { fetchPolicy: 'reload_revalidating_cache_data' // Load from server, fallback to cache } }); // the requested flow } catch (error) { console.error('Failed to fetch default audience flow:', error); } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>SDK, varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu durumda kullanıcılar en son verilere her zaman ulaşamayabilir; fakat internet bağlantılarının kalitesinden bağımsız olarak daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında ağ isteklerinden kaçınmak amacıyla güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırılıp yeniden yüklendiğinde ya da manuel temizleme yapıldığında temizlendiğini unutmayın.</p> | </SDKv4> <SDKv3> Remote config ve özel paywallları göstermeden önce bunlarla ilgili bilgileri getirmeniz gerekir. Bu konunun remote config ve özel paywallları ele aldığını unutmayın. Paywall Builder ile özelleştirilmiş paywallları getirme konusunda rehberlik için lütfen [Paywall Builder paywalllarını ve yapılandırmalarını getirme](capacitor-get-pb-paywalls) sayfasına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. [Bir paywall oluşturun ve ürünleri paywalla ekleyin](create-paywall) - Adapty Kontrol Paneli'nde. 3. [Placement'lar oluşturun ve paywallınızı placement'a ekleyin](create-placement) - Adapty Kontrol Paneli'nde. 4. [Adapty SDK'yı yükleyin](sdk-installation-capacitor) - mobil uygulamanıza. </details> ## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'deki ürünlerin birleşiminden oluşur. Bu platformlar arası ürünler paywallara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri göstermek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden [Paywall](paywalls) almanız gerekir. ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); // the requested paywall } catch (error) { console.error('Failed to fetch paywall:', error); } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve kullanım önerilerimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](capacitor-localizations-and-locale-codes) sayfasına bakın.</p> | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve hata durumunda önbellekteki verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, varsa önbellekteki verileri döndürmek için `'return_cache_data_else_load'` kullanmayı düşünebilirsiniz. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını unutmayın.</p> | | **params.loadTimeoutMs** | <p>isteğe bağlı</p><p>varsayılan: 5000 ms</p> | <p>Bu değer, metodun zaman aşımı süresini (milisaniye cinsinden) sınırlar. Zaman aşımına ulaşıldığında önbellekteki veriler veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeoutMs`'de belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | **Ürün ID'lerini kodunuza sabit olarak yazmayın.** Kodunuza sabit olarak yazmanız gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bugün iki ürün döndüren bir paywall yarın üç ürün döndürse bile kod değişikliği yapmadan hepsini göstermeniz gerekir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'leri listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywallı aldıktan sonra ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ paywall }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Ürün kimliği, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, büyük olasılıkla [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özelliklere ilişkin ayrıntılar için bağlantılı belgeye başvurun. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin cihazın dilayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Price** | Fiyatın yerelleştirilmiş halini göstermek için `product.price?.localizedString` kullanın. Bu yerelleştirme cihazın dil bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price?.amount` kullanabilirsiniz. Değer yerel para biriminde döner. İlgili para birimi sembolünü almak için `product.price?.currencySymbol` kullanın. | | **Subscription Period** | Dönemi (haftallık, aylık, yıllık vb.) göstermek için `product.subscription?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın diline göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscription?.subscriptionPeriod` kullanın. Buradan `unit` özelliğiyle süre birimini ('day', 'week', 'month', 'year' veya 'unknown') alabilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelikte `unit` özelliğinde `'month'`, `numberOfUnits` özelliğinde `3` görürsünüz. | | **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerip içermediğini rozet veya başka bir göstergeyle belirtmek için `product.subscription?.offer?.phases` özelliğine bakın. Bu liste en fazla iki indirim aşaması içerebilir: ücretsiz deneme aşaması ve başlangıç fiyatı aşaması. Her aşama nesnesinde şu yararlı özellikler bulunur:<br/>• `paymentMode`: `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` ve `'unknown'` değerlerini alan bir string. Ücretsiz denemeler `'free_trial'` türünde olur.<br/>• `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için bu alanda `0` arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın diline göre yerelleştirilmiş biçimde açıklayan bir string. Örneğin üç günlük bir deneme teklifi bu alanda `'3 days'` olarak görünür.<br/>• `subscriptionPeriod`: Alternatif olarak teklif döneminin ayrıntılarını bu özellikle alabilirsiniz. Teklifler için bir önceki bölümde açıklandığı gibi çalışır.<br/>• `localizedSubscriptionPeriod`: İndirim döneminin kullanıcının diline göre biçimlendirilmiş hali. | ## Varsayılan kitle paywallıyla paywall çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Paywalllar genellikle neredeyse anında çekildiğinden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa paywall çekme işlemi beklediğinizden daha uzun sürebilir. Bu durumlarda, hiç paywall göstermemek yerine düzgün bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir paywall göstermek isteyebilirsiniz. Bunu çözmek için belirtilen placement'ın **All Users** kitlesi için paywallını çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products-capacitor#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywall çekmek olduğunu unutmayın. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekirse zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürümdeki kullanıcıların render edilmeyen paywalllarla karşılaşabileceğini kabul etmek durumunda kalırsınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywallı görür; bu da ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybettiğiniz anlamına gelir. Bu dezavantajları daha hızlı paywall çekme avantajı için kabul etmeye hazırsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](fetch-paywalls-and-products-capacitor#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data' // Load from server, fallback to cache } }); // the requested paywall } catch (error) { console.error('Failed to fetch default audience paywall:', error); } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve kullanım önerilerimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](capacitor-localizations-and-locale-codes) sayfasına bakın.</p> | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve hata durumunda önbellekteki verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, varsa önbellekteki verileri döndürmek için `'return_cache_data_else_load'` kullanmayı düşünebilirsiniz. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını unutmayın.</p> | </SDKv3> --- # File: present-remote-config-paywalls-capacitor --- --- title: "Capacitor SDK'da remote config ile tasarlanmış paywall'u render etme" description: "Adapty Capacitor SDK'da remote config paywall'larını nasıl sunacağınızı keşfedin ve kullanıcı deneyimini kişiselleştirin." --- <SDKv4> Remote config kullanarak bir flow'u özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, neleri dahil edeceğinizi ve flow görünümünüzün nasıl görüneceğini siz belirlersiniz. Remote config aracılığıyla yapılandırılmış özel flow'unuzu sergileyebilmeniz için remote configuration'ı getirmeye yönelik bir metot sunuyoruz. ## Flow remote config'i alma ve sunma \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` dizisinde yapılandırılmış her dil için bir `AdaptyRemoteConfig` girişi taşır. Kullanıcının tercihiyle eşleşen dili seçin, ardından ihtiyacınız olan değerleri `data` alanından okuyun. ```typescript showLineNumbers try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); const config = flow.remoteConfigs?.find((c) => c.lang === 'en') ?? flow.remoteConfigs?.[0]; const headerText = config?.data?.['header_text']; } catch (error) { console.error('Failed to fetch flow:', error); } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel olarak çekici bir sayfada render edip bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil ekran boyutlarına ve yönlerine uyum sağladığından emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunabilirsiniz. :::warning Adapty analitiğinin huni ve A/B testi verilerini toplayabilmesi için aşağıda açıklandığı gibi [paywall görüntüleme etkinliğini kaydettiğinizden](present-remote-config-paywalls-capacitor#track-paywall-view-events) emin olun. ::: Flow'u görüntüledikten sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma işlemi gerçekleştirdiğinde, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](capacitor-making-purchases) bölümünü okuyun. [Yedek paywall olarak bir yedek paywall oluşturmanızı](capacitor-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Flow görüntüleme olaylarını izleme \{#track-paywall-view-events\} Adapty, flow'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplarken, flow görüntülemelerini kaydetmek için sizin müdahaleniz gerekir; çünkü bir kullanıcının flow'u ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir flow görüntüleme olayını kaydetmek için `.logShowFlow({ flow })` metodunu çağırmanız yeterlidir; bu, huniler ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülüyorsanız `.logShowFlow({ flow })` çağırmanıza gerek yoktur. Bu durumlarda Adapty görüntülemeleri otomatik olarak takip eder. ::: ```typescript showLineNumbers await adapty.logShowFlow({ flow }); ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :-------- | :------- |:-------------------------------------------------------------------------------------| | **flow** | zorunlu | `adapty.getFlow({ placementId })` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | </SDKv4> <SDKv3> Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağına ve nasıl görüneceğine siz karar verirsiniz. Remote config aracılığıyla yapılandırılmış özel paywall'ınızı gösterebilmeniz için remote configuration'ı çekmeye yarayan bir metot sunuyoruz. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve ihtiyacınız olan değerleri çıkarın. ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); const headerText = paywall.remoteConfig?.data?.['header_text']; } catch (error) { console.error('Failed to fetch paywall:', error); } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel olarak çekici bir sayfada render edip bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönelimlerine uyum sağladığından emin olun; bu sayede farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunulur. :::warning Adapty analitiğinin funnel'lar ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-capacitor#track-paywall-view-events-1) emin olun. ::: Paywallı gösterme işlemini tamamladıktan sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](capacitor-making-purchases) bölümünü okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](capacitor-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme olaylarını takip edin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın almaları otomatik olarak takip ederken, paywall görüntülemelerini kaydetmek için sizin müdahaleniz gerekir; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilirsiniz. Paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu, dönüşüm hunileri ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Paywall builder](adapty-paywall-builder) ile oluşturulan paywallları görüntülüyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```typescript showLineNumbers try { await adapty.logShowPaywall({ paywall }); } catch (error) { console.error('Failed to log paywall view:', error); } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- | :--------------------------------------------------------- | | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) nesnesi. | </SDKv3> --- # File: capacitor-making-purchases --- --- title: "Capacitor SDK ile mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın almaları ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları görüntülemek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, yalnızca bu paywall'ları göstermek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metodu kullanmanız gerekir. Bu metot, kullanıcıların paywalllarla etkileşime girerek istedikleri işlemleri gerçekleştirmesi için bir geçit görevi görür. Bir kullanıcının satın almak istediği ürün için paywallınızda aktif bir promosyon teklifi varsa, Adapty bunu satın alma sırasında otomatik olarak uygular. [Başlangıç yapılandırmasını](quickstart) tek bir adımı bile atlamamış şekilde tamamladığınızdan emin olun. Bu adım olmadan satın almaları doğrulayamayız. ## Satın alma işlemi gerçekleştirme \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın alma işlemleri otomatik olarak gerçekleştirilir; bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlamıyla uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](capacitor-implement-paywalls-manually) göz atın. ::: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('User is now subscribed!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- |:----------------------------------------------------------------------------------------------------------------------------| | **product** | zorunlu | `getPaywallProducts` ile flow üzerinden alınan bir [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **result** | Satın alma sonucunu belirten `type` alanı (`'success'`, `'user_cancelled'` veya `'pending'`) ve başarılı satın almalarda güncellenmiş [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) içeren `profile` alanını barındıran bir [`AdaptyPurchaseResult`](https://capacitor.adapty.io/types/adaptypurchaseresult) nesnesi. | ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu işlemin nasıl gerçekleşeceği uygulama mağazasına göre farklılık gösterir: - App Store'da abonelik, abonelik grubu içinde otomatik olarak güncellenir. Kullanıcı bir gruptan abonelik satın alırken başka bir grupta da aktif aboneliği varsa, her iki abonelik aynı anda aktif olur. - Google Play'de abonelik otomatik olarak güncellenmez. Geçişi aşağıda açıklandığı şekilde mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka biriyle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product, params: { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('Subscription updated successfully!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` | Parametre | Varlık | Açıklama | | :--------- | :------- | :----------------------------------------------------------- | | **params** | isteğe bağlı | [`MakePurchaseParamsInput`](https://capacitor.adapty.io/types/makepurchaseparamsinput) türünde, platforma özgü satın alma parametrelerini içeren bir nesne. | `MakePurchaseParamsInput` yapısı şunları içerir: ```typescript { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } ``` Google Geliştirici belgelerinde abonelikler ve değiştirme modları hakkında daha fazla bilgi edinebilirsiniz: - [Değişim modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değişim modları için önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değişim modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: Bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değişim modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik faturalama dönemi sona erdiğinde gerçekleşir. ### Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin birkaç aylık yenilenmez abonelik), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { pendingPrepaidPlansEnabled: true, }, } }); ``` ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanma ekranını göstermek için: ```typescript showLineNumbers try { await adapty.presentCodeRedemptionSheet(); } catch (error) { console.error('Failed to present code redemption sheet:', error); } ``` :::danger Gözlemlerimize göre, bazı uygulamalarda Teklif Kodu Kullanma ekranı güvenilir şekilde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için aşağıdaki formatta bir URL açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: --- # File: capacitor-restore-purchase --- --- title: "Capacitor SDK'da mobil uygulamada satın alma geçmişini geri yükleme" description: "Kesintisiz kullanıcı deneyimi sağlamak için Adapty'de satın alma geçmişini nasıl geri yükleyeceğinizi öğrenin." --- iOS ve Android'de Satın Almaları Geri Yükleme, kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden erişmesini sağlayan bir özelliktir. Bu özellik özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve önceki satın almalarına tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywallarda satın almalar, sizden ek bir kod gerektirmeksizin otomatik olarak geri yüklenir. Bu durumda bu adımı atlayabilirsiniz. ::: Paywallı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın alma geçmişini geri yüklemek için `.restorePurchases()` metodunu çağırın: ```typescript showLineNumbers try { const profile = await adapty.restorePurchases(); const isSubscribed = profile.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Restore access to paid features console.log('Access restored successfully!'); } else { console.log('No active subscriptions found'); } } catch (error) { console.error('Failed to restore purchases:', error); } ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | Bir [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) nesnesi. Bu model; access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir. Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin. | --- # File: implement-observer-mode-capacitor --- --- title: "Capacitor SDK'da Observer modunu uygulama" description: "Capacitor SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve henüz Adapty'ye tamamen geçmeye hazır değilseniz, [Observer mode](observer-vs-full-mode)'u inceleyebilirsiniz. Temel haliyle Observer Mode, gelişmiş analitik ve attribution ile analitik sistemlerle sorunsuz entegrasyon sunar. Eğer bu ihtiyaçlarınızı karşılıyorsa, tek yapmanız gereken: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak bunu etkinleştirmek. Kurulum talimatları için [Capacitor](sdk-installation-capacitor#activate-adapty-module-of-adapty-sdk) belgelerine bakın. 2. Mevcut satın alma altyapınızdan Adapty'ye [işlemleri bildirmek](report-transactions-observer-mode-capacitor). :::tip SDK v4'te, Adapty tarafından render edilen flow'ları ve paywall'ları Observer modunda da sunabilirsiniz: kullanıcı satın alma veya geri yükleme düğmesine dokunduğunda, SDK eylemi kodunuza devreder, böylece satın alma veya geri yüklemeyi kendiniz gerçekleştirebilirsiniz. Bkz. [Flow'ları Observer modunda sunma](capacitor-present-flows-in-observer-mode). ::: ### Observer mode kurulumu \{#observer-mode-setup\} Satın alma işlemlerini ve abonelik durumunu kendiniz yönetip Adapty'yi yalnızca abonelik olaylarını ve analitiği göndermek için kullanıyorsanız Observer mode'u etkinleştirin. :::important Observer mode'da çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle işlemleri kendiniz yönettiğinizden emin olun. ::: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { observerMode: true // Enable observer mode } }); } catch (error) { console.error('Failed to activate Adapty:', error); } ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | **observerMode** | [Observer mode](observer-vs-full-mode)'u kontrol eden boolean bir değer. Varsayılan değer `false`'tur. | ## Observer Mode'da Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer mode'da birkaç ek adım gereklidir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir: 1. [Remote config paywall'lar](present-remote-config-paywalls-capacitor) için paywall'ları normalde olduğu gibi gösterin. 2. Paywall'ları satın alma işlemleriyle [ilişkilendirin](report-transactions-observer-mode-capacitor). --- # File: report-transactions-observer-mode-capacitor --- --- title: "Capacitor SDK'da Observer Mode'da işlemleri raporlama" description: "Capacitor SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini raporlayın." --- Observer mode'da Adapty SDK, mevcut satın alma sisteminiz aracılığıyla gerçekleştirilen satın alımları kendi başına takip edemez. App store'dan gelen işlemleri manuel olarak raporlamanız gerekir. Analizlerde hata oluşmaması için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız kritik önem taşır. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanarak açıkça raporlayın. :::warning **İşlem raporlamayı atlamayın!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, işlem raporlarken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirerek paywall analizlerinin doğru olmasını sağlar. ```typescript showLineNumbers const variationId = paywall.variationId; try { await adapty.reportTransaction({ transactionId: 'your_transaction_id', variationId: variationId }); } catch (error) { console.error('Failed to report transaction:', error); } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- | ------------------------------------------------------------ | | **transactionId** | zorunlu | <ul><li> iOS için: İşlemin tanımlayıcısı.</li><li> Android için: Satın almanın string tanımlayıcısı (`purchase.getOrderId`); burada purchase, billing kütüphanesinin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | **variationId** | isteğe bağlı | Varyasyonun string tanımlayıcısı. Bunu [AdaptyPaywall](https://capacitor.adapty.io/interfaces/adaptypaywall) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | --- # File: capacitor-user --- --- title: "Kullanıcılar ve erişim" description: "Capacitor uygulamanızda Adapty SDK ile kullanıcılar ve access level'lar üzerinde nasıl çalışılacağını öğrenin." --- <CustomDocCardList /> --- # File: capacitor-identifying-users --- --- title: "Capacitor SDK'da kullanıcıları tanımlama" description: "Adapty SDK ile Capacitor uygulamanızda kullanıcıları nasıl tanımlayacağınızı öğrenin." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi belirlemeniz gerekir. Kullanıcıları Customer User ID'lerine göre [Profiller](profiles-crm) bölümünde bulabilir ve [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz; bu ID tüm entegrasyonlara gönderilecektir. ### Yapılandırma sırasında customer user ID ayarlama \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçirmeniz yeterlidir: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { customerUserId: 'YOUR_USER_ID' } }); } catch (error) { console.error('Failed to activate Adapty:', error); } ``` ### Yapılandırma sonrasında customer user ID ayarlama \{#setting-customer-user-id-after-configuration\} SDK yapılandırması sırasında bir kullanıcı ID'niz yoksa, daha sonra istediğiniz zaman `.identify()` metoduyla belirleyebilirsiniz. Bu metodun en yaygın kullanım senaryoları, kayıt veya giriş sonrasında kullanıcının anonim olmaktan çıkıp kimliği doğrulanmış bir kullanıcıya geçtiği anlardır. ```typescript showLineNumbers try { await adapty.identify({ customerUserId: 'YOUR_USER_ID' }); console.log('User identified successfully'); } catch (error) { console.error('Failed to identify user:', error); } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **customerUserId** | zorunlu | Bir string kullanıcı tanımlayıcısı. | :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Bir kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda Adapty sunucuları o kullanıcı hakkında zaten bilgiye sahip olabilir. Bu senaryolarda Adapty SDK otomatik olarak yeni kullanıcıyla çalışmaya geçer. Anonim kullanıcıya özel özellikler veya üçüncü taraf ağlardan attribution gibi veriler aktardıysanız, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden talep etmeniz gerektiğini unutmayın; zira yeni kullanıcının verileri farklı olabilir. ::: ### Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\} Kullanıcıyı istediğiniz zaman `.logout()` metodunu çağırarak çıkışa zorlayabilirsiniz: ```typescript showLineNumbers try { await adapty.logout(); console.log('User logged out successfully'); } catch (error) { console.error('Failed to logout user:', error); } ``` Ardından `.identify()` metodunu kullanarak kullanıcı girişi yapabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle ilişkilendirir; böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulan kararlı bir UUID kullanın ve aynı hesap için farklı cihazlarda da aynı UUID'yi yeniden kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş olur. Token'ı iki şekilde ayarlayabilirsiniz: SDK aktivasyonu sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmelisiniz. Yalnızca token'ı geçerseniz, işleme dahil edilmez. ::: ```typescript showLineNumbers // During configuration: await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { customerUserId: 'YOUR_USER_ID', ios: { appAccountToken: "YOUR_APP_ACCOUNT_TOKEN" }, } }); // Or when identifying users await adapty.identify({ customerUserId: 'YOUR_USER_ID', params: { ios: { appAccountToken: 'YOUR_APP_ACCOUNT_TOKEN' }, } }); ``` ### Gizlenmiş hesap ID'lerini ayarlama (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryolarında gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in kullanıcı bilgilerini anonim tutarken satın almaları tanımlamasına yardımcı olur; bu durum özellikle sahtekarlık önleme ve analitik açısından önem taşır. Uygulamanız hassas kullanıcı verisi işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri ayarlamanız gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın almaları takip etmesine olanak tanır. ```typescript showLineNumbers // During configuration: await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' }, } }); // Or when identifying users await adapty.identify({ customerUserId: 'YOUR_USER_ID', params: { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' }, } }); ``` ## Cihazlar arası kullanıcı tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: capacitor-setting-user-attributes --- --- title: "Capacitor SDK'da kullanıcı özellikleri ayarlama" description: "Adapty SDK ile Capacitor uygulamanızda kullanıcı özelliklerini ve profil verilerini nasıl güncelleyeceğinizi öğrenin." --- Uygulamanızın kullanıcılarına e-posta, telefon numarası gibi isteğe bağlı özellikler atayabilirsiniz. Bu özellikleri kullanarak kullanıcı [segmentleri](segments) oluşturabilir ya da bunları CRM'de görüntüleyebilirsiniz. ### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```typescript showLineNumbers const params = { email: 'email@email.com', phoneNumber: '+18888888888', firstName: 'John', lastName: 'Appleseed', gender: 'other', birthday: new Date().toISOString(), }; try { await adapty.updateProfile(params); console.log('Profile updated successfully'); } catch (error) { console.error('Failed to update profile:', error); } ``` `updateProfile` metoduyla daha önce ayarladığınız özelliklerin sıfırlanmayacağını unutmayın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarların listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters` için izin verilen anahtarlar ve değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | **email** | String | | **phoneNumber** | String | | **firstName** | String | | **lastName** | String | | **gender** | Enum, izin verilen değerler: `'female'`, `'male'`, `'other'` | | **birthday** | ISO formatında tarih dizesi | ### Özel kullanıcı özellikleri \{#custom-user-attributes\} Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanım alışkanlıklarıyla ilgilidir. Örneğin fitness uygulamalarında haftada yapılan egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi seviyesi gibi veriler olabilir. Bu özellikleri segmentlerde kullanarak hedefli paywall'lar ve teklifler oluşturabilir; hangi ürün metriklerinin geliri en çok etkilediğini anlamak için analizlerde de yararlanabilirsiniz. ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); console.log('Custom attributes updated successfully'); } catch (error) { console.error('Failed to update custom attributes:', error); } ``` Mevcut anahtarları kaldırmak için değer olarak `null` gönderin: ```typescript showLineNumbers try { // to remove keys, pass null as their values await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); console.log('Custom attributes removed successfully'); } catch (error) { console.error('Failed to remove custom attributes:', error); } ``` Bazen hangi özel özelliklerin daha önce ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini göz önünde bulundurun; kullanıcı özellikleri farklı cihazlardan herhangi bir anda gönderilebileceğinden, sunucudaki özellikler son eşitlemeden bu yana değişmiş olabilir. ::: ### Sınırlamalar \{#limits\} - Kullanıcı başına en fazla 30 özel özellik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adları alfanümerik karakterler ve şunlardan herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakter uzunluğunda bir string veya float olabilir. --- # File: capacitor-listen-subscription-changes --- --- title: "Capacitor SDK'da abonelik durumunu kontrol etme" description: "Capacitor uygulamanızda müşteri elde tutmayı iyileştirmek için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek artık çok kolay. Ürün kimliklerini manuel olarak kodunuza eklemenize gerek yok. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. <details> <summary>Abonelik durumunu kontrol etmeye başlamadan önce (Genişletmek için tıklayın)</summary> - iOS için [App Store Server Notifications](enable-app-store-server-notifications) kurulumunu yapın - Android için [Gerçek Zamanlı Geliştirici Bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) kurulumunu yapın </details> ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile) nesnesinin özellikleridir. Uygulamanız başladığında, örneğin [bir kullanıcıyı tanımlarken](capacitor-identifying-users#setting-customer-user-id-on-configuration), profili almanızı ve ardından değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini tekrar tekrar istemek zorunda kalmadan kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Profil güncellemelerini dinleme, access level değişiklikleri dahil](capacitor-listen-subscription-changes) bölümünde açıklandığı gibi profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Sunucudan access level bilgisini alma \{#retrieving-the-access-level-from-the-server\} Sunucudan access level bilgisini almak için `.getProfile()` metodunu kullanın: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); console.log('Profile retrieved successfully'); } catch (error) { console.error('Failed to get profile:', error); } ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | Bir [AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile) nesnesi. Genellikle, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz gerekir. `.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu sağlar. Herhangi bir nedenle (ör. internet bağlantısı olmaması) Adapty SDK sunucudan bilgi alamazsa, önbellekteki veriler döndürülür. Ayrıca Adapty SDK'nın bu bilgileri mümkün olduğunca güncel tutmak için `AdaptyProfile` önbelleğini düzenli aralıklarla güncellediğini de belirtmek gerekir. | `.getProfile()` metodu, access level durumunu alabileceğiniz kullanıcı profilini size sağlar. Bir uygulamada birden fazla access level'a sahip olabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız olarak abonelik satıyorsanız, "sports" ve "science" adında access level'lar oluşturabilirsiniz. Ancak çoğu zaman yalnızca bir access level'a ihtiyaç duyacaksınız; bu durumda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels?.['premium']?.isActive; if (isActive) { // Grant access to premium features console.log('User has premium access'); } else { console.log('User does not have premium access'); } } catch (error) { console.error('Failed to check subscription status:', error); } ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde, Adapty bir olay tetikler. Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir: ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addListener('onLatestProfileLoad', (data) => { const profile = data.profile; const isActive = profile.accessLevels?.['premium']?.isActive; if (isActive) { console.log('Subscription status updated: User has premium access'); } else { console.log('Subscription status updated: User does not have premium access'); } }); ``` Adapty, uygulama başlangıcında da bir olay tetikler. Bu durumda önbelleğe alınmış abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'da uygulanan önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu kullanılamaz olsa bile, profilin abonelik durumuna ilişkin bilgilere önbellekten erişilebilir. Ancak, önbellekten doğrudan veri isteği yapılamadığını belirtmek gerekir. SDK, profille ilgili herhangi bir güncelleme veya değişiklik olup olmadığını kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler veya diğer güncellemeler gibi herhangi bir değişiklik varsa, sunucuyla senkronize tutmak amacıyla önbelleğe alınan veriye gönderilir. --- # File: capacitor-deal-with-att --- --- title: "Capacitor SDK'da ATT ile başa çıkma" description: "Abonelik kurulumu ve yönetimini kolaylaştırmak için Capacitor'da Adapty ile başlayın." --- Uygulamanız AppTrackingTransparency framework'ünü kullanıyor ve kullanıcıya uygulama takibi için yetkilendirme isteği gösteriyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye iletmeniz gerekir. ```typescript showLineNumbers try { await adapty.updateProfile({ appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); console.log('ATT status updated successfully'); } catch (error) { console.error('Failed to update ATT status:', error); } ``` :::warning Bu değeri, değiştiği anda mümkün olan en kısa sürede iletmenizi şiddetle tavsiye ederiz. Yalnızca bu şekilde veriler, yapılandırdığınız entegrasyonlara zamanında gönderilebilir. ::: --- # File: capacitor-onboardings --- --- title: "Onboardings" description: "Capacitor uygulamanızda Adapty SDK ile onboarding'lerin nasıl kullanılacağını öğrenin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmış olup gelecekteki bir sürümde tamamen kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](capacitor-get-pb-paywalls) kullanın: onboarding'lerin aksine WebView içinde çalışan bu yapının yerine, flow'lar cihazda yerel olarak render edilir — daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yüklenme süreleri ve WebView çalışma zamanı bağımlılığı olmadan kullanım sunar. Başlamak için [Flow'ları ve paywall'ları edinin](capacitor-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleyin](capacitor-present-paywalls) sayfalarına göz atın. ::: <CustomDocCardList /> --- # File: capacitor-get-onboardings --- --- title: "Capacitor SDK'da onboarding'leri al" description: "Adapty'de Capacitor için onboarding'lerin nasıl alınacağını öğrenin." --- :::warning **Onboardinglar SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık düzeltme veya iyileştirme almamaktadır. Bunun yerine [flow'ları](capacitor-get-pb-paywalls) kullanın: WebView içinde çalışan onboardingların aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı olmaksızın çalışma imkânı sunar. Başlamak için [Flow'ları ve paywallları edinin](capacitor-get-pb-paywalls) ve [Flow'ları ve paywallları görüntüleyin](capacitor-present-paywalls) sayfalarına bakın. ::: Adapty Kontrol Paneli'ndeki builder ile [onboarding'inizin görsel kısmını tasarladıktan](design-onboarding) sonra, bunu Capacitor uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkilendirilmiş onboarding'i ve onun görünüm yapılandırmasını almaktır. Başlamadan önce şunları kontrol edin: 1. [Bir onboarding oluşturdunuz](create-onboarding). 2. Onboarding'i bir [placement](placements)'a eklediniz. ## Onboarding'i getirme \{#fetch-onboarding\} No-code builder'ımızla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirmesi ve görüntülemesi gereken bir yapılandırma içeren container olarak saklanır. Bu container tüm deneyimi yönetir: hangi içeriğin görüneceği, nasıl sunulacağı ve kullanıcı etkileşimlerinin (quiz yanıtları veya form girişleri gibi) nasıl işleneceği. Container ayrıca analitik olaylarını otomatik olarak izlediğinden ayrı görünüm takibi uygulamanız gerekmez. En iyi performans için, kullanıcılara göstermeden önce görsellerin indirilmesine yeterli zaman tanımak amacıyla onboarding yapılandırmasını erken getirin. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```typescript showLineNumbers try { const onboarding = await adapty.getOnboarding({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); console.log('Onboarding fetched successfully'); } catch (error) { console.error('Failed to fetch onboarding:', error); } ``` Ardından, bir görünüm örneği oluşturmak için `createOnboardingView` metodunu çağırın. :::warning `createOnboardingView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `createOnboardingView` metodunu yeniden çağırın. ::: ```typescript showLineNumbers if (onboarding.hasViewConfiguration) { try { const view = await createOnboardingView(onboarding); console.log('Onboarding view created successfully'); } catch (error) { console.error('Failed to create onboarding view:', error); } } else { // Use your custom logic console.log('Onboarding does not have view configuration'); } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, mevcut olduğunda önbelleğe alınmış verileri döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin, uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p> | | **params.loadTimeoutMs** | <p>isteğe bağlı</p><p>varsayılan: 5000 ms</p> | <p>Bu değer, bu metot için zaman aşımını (milisaniye cinsinden) sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metot, `loadTimeoutMs` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | |:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding** | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyOnboarding`](https://capacitor.adapty.io/interfaces/adaptyonboarding) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding getirmeyi hızlandırın \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Onboarding'ler genellikle neredeyse anında getirilir, bu nedenle bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir onboarding'i getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bu sorunu gidermek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için onboarding'i getiren `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Getirme](#fetch-onboarding) bölümünde açıklandığı şekilde `getOnboarding` metoduyla onboarding getirmek olduğunu anlamak önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı değerlendirin; çünkü ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlara yol açabilir; geriye dönük uyumlu tasarımlar yapmanızı ya da eski sürümlerin hatalı görüntülenebileceğini kabul etmenizi gerektirir. - **Kişiselleştirme yok**: Yalnızca "Tüm Kullanıcılar" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı getirme bu dezavantajlardan daha önemliyse aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```typescript showLineNumbers try { const onboarding = await adapty.getOnboardingForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data' // Load from server, fallback to cache } }); console.log('Default audience onboarding fetched successfully'); } catch (error) { console.error('Failed to fetch default audience onboarding:', error); } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **params.fetchPolicy** | <p>isteğe bağlı</p><p>varsayılan: `'reload_revalidating_cache_data'`</p> | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, mevcut olduğunda önbelleğe alınmış verileri döndürmek için `'return_cache_data_else_load'` kullanmayı değerlendirin. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin, uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p> | --- # File: capacitor-present-onboardings --- --- title: "Capacitor SDK'da onboarding'leri sunma" description: "Dönüşümleri ve geliri artırmak için Capacitor'da onboarding'lerin nasıl sunulacağını keşfedin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](capacitor-get-pb-paywalls) kullanın: WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir yerel görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow'ları ve paywallları edinin](capacitor-get-pb-paywalls) ve [Flow'ları ve paywallları görüntüleyin](capacitor-present-paywalls) sayfalarına bakın. ::: Onboarding'i builder ile özelleştirdiyseniz, kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render işlemi yapmanıza gerek yoktur. Böyle bir onboarding, hem onboarding içinde gösterilecekleri hem de bunların nasıl gösterileceğini içerir. Başlamadan önce şunları tamamladığınızdan emin olun: 1. Bir [onboarding oluşturdunuz](create-onboarding). 2. Onboarding'i bir [placement](placements)'a eklediniz. ## Onboarding'i sunma \{#present-onboarding\} Bir onboarding'i görüntülemek için `createOnboardingView` metodu ile oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Onboarding'i tekrar görüntülemeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createOnboardingView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak hataya yol açabilir. ::: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onClose: (actionId, meta) => { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom: (actionId, meta) => { console.log('Custom action:', actionId); return false; // Don't close the onboarding } }); await view.present(); console.log('Onboarding presented successfully'); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` ## Onboardinglerde bağlantıların nasıl açıldığını özelleştirin \{#customize-how-links-open-in-onboardings\} :::important Onboardinglerde bağlantıların nasıl açıldığını özelleştirme özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboardinglerdeki bağlantılar uygulama içi tarayıcıda açılır. Bu, web sayfalarını uygulamanız içinde göstererek kullanıcıların uygulama değiştirmeden görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sağlar. Bağlantıların bunun yerine harici tarayıcıda açılmasını tercih ediyorsanız, `openIn` parametresini `browser_out_app` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```typescript showLineNumbers await view.present({ openIn: 'browser_out_app' }); // default — browser_in_app ``` ## Sonraki adımlar \{#next-steps\} Onboarding'inizi sunduktan sonra [kullanıcı etkileşimlerini ve olayları ele almayı](capacitor-handling-onboarding-events) öğrenebilirsiniz. Kullanıcı eylemlerine yanıt vermek ve analizleri takip etmek için onboarding olaylarının nasıl işleneceğini öğrenin. --- # File: capacitor-handling-onboarding-events --- --- title: "Capacitor SDK'da onboarding olaylarını yönetin" description: "Adapty kullanarak Capacitor'da onboarding ile ilgili olayları yönetin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](capacitor-get-pb-paywalls)'ları kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı ortadan kalkar. Başlamak için [Flow ve paywall'ları alma](capacitor-get-pb-paywalls) ve [Flow ve paywall'ları gösterme](capacitor-present-paywalls) konularına bakın. ::: Oluşturucuyla yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bağımsız ekran sunumu için bu olayları işlemek amacıyla `setEventHandlers` metodunu kullanın. Başlamadan önce şunları yaptığınızdan emin olun: 1. [Bir onboarding oluşturdunuz](create-onboarding). 2. Onboarding'i bir [placement](placements)'a eklediniz. ## Olay işleyicilerini ayarlama \{#set-up-event-handlers\} Onboarding olaylarını işlemek için `view.setEventHandlers` metodunu kullanın: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event); }, onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom(actionId, meta) { console.log('Custom action:', actionId); return false; // Don't close the onboarding }, onPaywall(actionId, meta) { console.log('Paywall action:', actionId); view.dismiss().then(() => { openPaywall(actionId); }); }, onStateUpdated(action, meta) { console.log('State updated:', action); }, onFinishedLoading(meta) { console.log('Onboarding finished loading'); }, onError(error) { console.error('Onboarding error:', error); }, }); await view.present(); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## Olay türleri \{#event-types\} Aşağıdaki bölümler, yönetebileceğiniz farklı olay türlerini açıklamaktadır. ### Özel eylemleri yönetme \{#handle-custom-actions\} Builder'da bir düğmeye **özel** eylem ekleyebilir ve ona bir ID atayabilirsiniz. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu ID'yi kodunuzda kullanarak özel bir eylem olarak işleyebilirsiniz. Örneğin, kullanıcı **Login** veya **Allow notifications** gibi özel bir butona dokunduğunda, event handler `actionId` parametresiyle tetiklenir ve bu parametre builder'daki **Action ID** değeriyle eşleşir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```typescript showLineNumbers view.setEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': console.log('Login action triggered'); break; case 'allow_notifications': console.log('Allow notifications action triggered'); break; } return false; // Don't close the onboarding }, }); ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allow_notifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### Onboarding yüklemesini tamamlama \{#finishing-loading-onboarding\} Bir onboarding yüklemesi tamamlandığında bu olay tetiklenir: ```typescript showLineNumbers view.setEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### Onboarding'i kapatma \{#closing-onboarding\} Onboarding, kullanıcı **Close** eylemine atanmış bir düğmeye dokunduğunda kapalı sayılır. <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini göstermeyi durdurmanız gerekir. ::: ```typescript showLineNumbers view.setEventHandlers({ onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Onboarding'in kapanmasına izin ver }, }); ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### Bir paywall açma \{#opening-a-paywall\} :::tip Onboarding içinde bir paywall açmak istiyorsanız bu olayı ele alın. Paywall kapandıktan sonra açmak istiyorsanız daha doğrudan bir yol var: kapatma eylemini ele alın ve olay verisine dayanmadan bir paywall açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, eylem ID'sini bir paywall placement ID'sine eşit yapmaktır. iOS'ta aynı anda yalnızca bir görünüm (paywall veya onboarding) ekranda gösterilebilir. Bir onboarding'in üzerine paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışırsanız bunun yerine paywall kapanır ve onboarding görünür kalır. Bunu önlemek için paywall'ı sunmadan önce her zaman onboarding görünümünü kapatın. ```typescript showLineNumbers view.setEventHandlers({ onPaywall(actionId, meta) { // Ödeme ekranını göstermeden önce onboarding'i kapat view.dismiss().then(() => { openPaywall(actionId); }); }, }); async function openPaywall(placementId: string) { // Paywall açma mantığınızı buraya uygulayın } ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### Navigasyonu izleme \{#tracking-navigation\} Onboarding flow'u sırasında çeşitli navigasyon olayları gerçekleştiğinde bir analytics olayı alırsınız: ```typescript showLineNumbers view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event.type, meta.onboardingId); }, }); ``` `event` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `onboardingStarted` | Onboarding yüklendiğinde | | `screenPresented` | Herhangi bir ekran gösterildiğinde | | `screenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcıdan gelen yanıt) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir işlem gerçekleştirdiğinde tetiklenir. | | `secondScreenPresented` | İkinci ekran gösterildiğinde | | `userEmailCollected` | Kullanıcının e-postası giriş alanı aracılığıyla toplandığında tetiklenir | | `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyaç duyuyorsanız [son ekrana `final` ID'sini atayın](design-onboarding). | | `unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veriler) içerir | Her etkinlik, aşağıdakileri içeren `meta` bilgisini barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding flow'unun benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Mevcut ekranın flow içindeki konumu | | `screensTotal` | Flow'daki toplam ekran sayısı | <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: capacitor-onboarding-input --- --- title: "Capacitor SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Capacitor uygulamanızdaki onboarding verilerini kaydedin ve kullanın." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde tamamen kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](capacitor-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda doğrudan native olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı native bir görünüm, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı ortadan kalkar. Başlamak için [Flow ve paywall alma](capacitor-get-pb-paywalls) ile [Flow ve paywall gösterme](capacitor-present-paywalls) sayfalarına bakın. ::: Kullanıcılarınız bir quiz sorusuna yanıt verdiğinde veya bir giriş alanına veri girdiğinde `onStateUpdated` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```typescript view.setEventHandlers({ onStateUpdated(action, meta) { // Process data }, }); ``` Aksiyon formatını [buradan](https://capacitor.adapty.io/types/onboardingstateupdatedaction) inceleyebilirsiniz. <Details> <summary>Kaydedilen veri örnekleri (format, uygulamanıza göre farklılık gösterebilir)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri anında kullanıcı profiliyle ilişkilendirmek ve aynı bilgileri tekrar sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](capacitor-setting-user-attributes) girilen verilerle güncellemeniz gerekir. Örneğin, kullanıcılardan `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini de girmelerini istiyorsunuz. Uygulama kodunuzda bu şu şekilde görünebilir: ```typescript showLineNumbers view.setEventHandlers({ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams: any = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile({ params: profileParams }).catch((error) => { // handle the error }); } } }, }); ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboardinglarda quiz kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara sporla ilgili deneyimlerini sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ile ürünler gösterebilirsiniz. 1. Onboarding builder'da [bir quiz ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler belirleyin](capacitor-setting-user-attributes). ```typescript showLineNumbers view.setEventHandlers({ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams: any = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile({ params: profileParams }).catch((error) => { // handle the error }); } } }, }); ``` 3. Her özel nitelik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda placement için [bir paywall gösterin](capacitor-paywalls). Onboardingde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna yanıt olarak](capacitor-handling-onboarding-events#opening-a-paywall) uygulayın. --- # File: capacitor-best-practices --- --- title: "Capacitor SDK'da en iyi uygulamalar" description: "Adapty SDK'yı Capacitor üzerinde entegre etmek için referans kalıplar — çağrı sırası, hata yönetimi ve diğer production hazırlık kuralları." --- <CustomDocCardList /> --- # File: capacitor-sdk-call-order --- --- title: "Capacitor SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak premium erişim kayıplarını, eksik attribution sorunlarını ve aralıklı #2002 hatalarını önleyin." --- `adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağıramazsınız. Bu metot sonuçlanmadan SDK'nın herhangi bir durumu yoktur. `activate()` bitmeden veya onunla paralel olarak yapılan her çağrı [`#2002 notActivated`](capacitor-handle-errors#custom-network-codes) hatasıyla başarısız olur. Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, `adapty.identify()` metodunu o noktada çağırın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metodları çağırmayın. Bununla yarışan çağrılar ya [`#3006 profileWasChanged`](capacitor-handle-errors#custom-network-codes) hatasıyla başarısız olur ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu olduğunda attribution, `appsflyer_id` gibi MMP kimlikleri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` metodunu atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kuralı izler. `adapty.activate` çağırmadan önce bunları başlatın ve UID geri çağrılarını bekleyin. Aksi takdirde MMP kimliği kısa ömürlü anonim bir profile düşer ve tanımlı profile her zaman aktarılmaz. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıralama \{#the-correct-order\} Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. Adımlar**: Her uygulama için zorunludur. Önce SDK'yı etkinleştirin, ardından SDK metodlarını çağırın. - **1. ve 3. Adımlar**: Yalnızca bir MMP veya analitik SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. Adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini uygulama açıldıktan sonra topluyorsa gereklidir. Uygulama başlatılırken customer user ID'niz varsa, bunu doğrudan `activate()` içine aktarın (adım 2a). Bu yol hiçbir zaman anonim bir profil oluşturmaz, dolayısıyla 4. adım gereksizdir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analytics SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlangıcı, ilk sırada | MMP'nin UID callback'ini bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `adapty.activate({ apiKey: '...', params: { customerUserId: '...' } })` | Uygulama başlangıcı, 1. adımdan sonra, customer user ID'ye sahipseniz | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `adapty.activate({ apiKey: '...' })` — `customerUserId` olmadan | Uygulama başlangıcı, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `adapty.setIntegrationIdentifier({ key: '...', value: '...' })` | 2. adımdan sonra, herhangi bir kullanıcı eylemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için gereklidir. | | 4 | `await adapty.identify({ customerUserId: 'YOUR_USER_ID' })` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulamalı 2b yolunda | Her zaman `await` kullanın. `identify` sırasında eşzamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar. | | 5 | `getPaywall` (SDK v4'te `getFlow`), `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi hâlde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::important Bu adımların atlanması; geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde `appsflyer_id` eksikliğine ve yanlış kitle için paywall döndürülmesine yol açar. ::: ## Web2app ve web-funnel yüklemeleri \{#web2app-and-web-funnel-installs\} Kullanıcılar web üzerinden ödeme yapıp (Stripe, Paddle) sonradan uygulamayı yüklediğinde, cihazda ilk çalışan `activate()` yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Müşteri kullanıcı kimliğini uygulama açılmadan önce çözümleyebiliyorsanız (kimlik doğrulama akışından veya install referrer'dan), doğrudan `activate()` içine aktarın. Aksi takdirde, `identify({ customerUserId: 'YOUR_USER_ID' })` ve ardından `restorePurchases` çağrısı yapana kadar web satın alımı cihazda görünmez. Her web ödemesiyle gönderilecek metadata için bkz.: - [Stripe](stripe) - [Paddle](paddle) --- # File: capacitor-optimize-paywall-fetching --- --- title: "Capacitor SDK'da paywall getirmeyi optimize edin" description: "Adapty paywalllarını güvenilir şekilde getirin: Capacitor için zamanlama, önbellekleme ve yedek paywall desenleri." --- Capacitor'da güvenilir bir paywall getirme işlemi üç şeyi başarır: hızlı render eder, kitleye hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz şekilde yedek paywall'a geçer. Aşağıdaki kurallar bu sonuca ulaşmak için zamanlama, önbellekleme ve yedek paywall desenlerini kapsar. :::tip Aşağıdaki kurallar `adapty.activate()` ve `adapty.identify()` çağrılarının zaten tamamlanmış olduğunu varsayar. Bkz. [Capacitor SDK'da çağrı sırası](capacitor-sdk-call-order). ::: Aşağıdaki öneriler v3 metod adlarını kullanmaktadır. SDK v4'te `getPaywall`, `getFlow` olarak yeniden adlandırılmıştır ([migration kılavuzuna bakın](migration-to-capacitor-sdk-v4)) — her kural değişmeden geçerlidir. ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Yapılması gereken | Yapılmaması gereken | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı çekin. | Başlatma sırasında tüm placement'ları eş zamanlı olarak önceden çekin. | Toplu ön çekme ana iş parçacığını bloke eder ve bu sürede siyah ekrana neden olur. | | `getPaywall`'ı attribution çözümlendikten sonra çekin — örneğin `activate`'ten 1–2 saniye sonra ya da `onLatestProfileLoad` dinleyicisi tetiklendikten sonra. | `getPaywall`'ı uygulama başlatılırken `App.tsx` içinde çağırın. | Attribution henüz gelmemiştir. Paywall varsayılan kitleye göre çözümlenir ve segmentler ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeoutMs` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ın bitmesini süresiz bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf kullanıcılar ağ düzelenene kadar — ya da uygulamayı kapatana kadar — boş ekran görür. | `fetchPolicy` ve `loadTimeoutMs` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products-capacitor) bölümüne, doğru placement'ı seçmek için ise [Placement'lar](placements) bölümüne bakın. ## Zayıf bağlantı için ayarlamalar \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantı yaşanan pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunlarından etkilenen bölgeler): - Çok ilk getirme dışındaki her getirme işleminde `fetchPolicy: 'return_cache_data_else_load'` ayarını kullanın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeoutMs` değerini 3000–5000 milisaniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin. - Paywall gösterimini `adapty.getProfile()` çağrısına bağlamayın. `getPaywall` işlemini bağımsız olarak çağırın; böylece yavaş bir profil yüklemesi arayüzü bloke etmez. --- # File: capacitor-show-aa-targeted-paywall --- --- title: "Capacitor SDK'da ilk başlatmada AA hedefli bir paywall gösterme" description: "Bir paywallı hemen gösterin ve attribution uygulandıktan sonra Apple Ads kullanıcıları için Capacitor'da yükseltin; bunun için AdaptyProfile.appliedAttributionSources kullanın." --- Apple Ads (AA) attribution, `adapty.activate()` sonrasında asenkron olarak gelir. İlk açılışta genellikle henüz gelmemiş olduğundan, `getFlow` varsayılan kitleye göre çözümlenir ve Apple Ads kullanıcıları AA-segmentli paywallınızı kaçırır. Paywall'ı attribution gelene kadar geciktirmek yerine, hemen bir tane gösterin ve AA attribution uygulandığında yenileyin; böylece Apple Ads kullanıcıları hedefli varyantı görürken diğer herkes hiç beklemeden bir paywall görür. `AdaptyProfile.appliedAttributionSources`, AA attribution'ın ne zaman uygulandığını size bildirir. ## Başlamadan önce \{#before-you-start\} İhtiyacınız olanlar: - Adapty Capacitor SDK **3.17.1** veya üstü. - Uygulamanız için Adapty'de Apple Ads yapılandırılmış olmalı. Bkz. [Apple Ads](apple-search-ads). ## Nasıl çalışır \{#how-it-works\} `adapty.activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution verisi ister ve sonucu Adapty'nin backend'ine iletir. AA, profil için aktif attribution kaynağı haline geldiğinde SDK, `onLatestProfileLoad` dinleyicinize güncellenmiş bir `AdaptyProfile` iletir; bu profildeki `appliedAttributionSources` dizisinde `'apple_search_ads'` yer alır. Bu sayede paywall'ı iki adımda yükleyebilirsiniz: 1. `getFlow`'u hemen çağırın. Henüz attribution uygulanmadığından Adapty isteği varsayılan kitleye göre çözümler ve kullanıcı hemen bir paywall görür. 2. `'apple_search_ads'` göründüğünde `getFlow`'u tekrar çağırın. Adapty artık isteği Apple Ads kitlesine göre çözümleyerek hedeflenmiş paywall'ı döndürür ve bu paywall ilkinin yerini alır. `appliedAttributionSources` boş olabilir veya hiç bulunmayabilir. Bu şu anlama gelir: - Bu profil için Apple Ads attribution henüz işlenmemiştir ya da - hiç attribution gelmemiştir. Her iki durumda da 1. adım güvenlidir — Adapty, isteği mevcut profil durumuna göre eşleşen kitleyle, genellikle varsayılan kitleyle çözümler. 2. adım yalnızca `'apple_search_ads'` göründükten sonra çalışır. :::important Sonraki her başlatmada, önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `'apple_search_ads'` bilgisini taşır; dolayısıyla ilk `getFlow` çağrısı doğrudan Apple Ads segmentine göre paywall'ı döndürür — ikinci bir istek veya görünür bir değişiklik olmaz. İki adımlı flow yalnızca attribution henüz işlenirken, ilk başlatmada önem taşır. ::: ## Uygulama \{#implementation\} Hemen bir paywall göster, ardından `'apple_search_ads'` olayını dinle ve geldiğinde paywall'ı yenile. 1. **SDK'yı etkinleştirin.** Bkz. [Capacitor SDK'yı yükleyin ve yapılandırın](sdk-installation-capacitor). 2. **Bir paywall yükleyin ve gösterin** — `getFlow` ile her zamanki gibi yapın, attribution için beklemeyin. 3. **Profil güncellemelerini dinleyin** — `adapty.addListener('onLatestProfileLoad', …)` ile `'apple_search_ads'` verisini izleyin. Göründüğünde paywall'ı yeniden çekip güncel olanı gösterin. Dinleyiciyi henüz kurmadıysanız bkz. [Abonelik güncellemelerini dinleyin](capacitor-check-subscription-status#listen-to-subscription-updates): ```typescript const listener = await adapty.addListener('onLatestProfileLoad', async ({ profile }) => { if (!profile.appliedAttributionSources?.includes('apple_search_ads')) return; const targeted = await adapty.getFlow({ placementId }); // present the targeted flow in place of the first one }); // Call listener.remove() after the upgrade, or after a timeout (see below). ``` 4. **Zaman aşımından sonra dinlemeyi durdurun.** Kullanıcıların büyük çoğunluğu hiçbir zaman Apple Ads attribution verisi almaz; bu nedenle dinleyiciyi tüm oturum boyunca açık tutmak yerine bir süre sonra kaldırın. İstek başarısız olduğunda kullanıcının her zaman bir şey görmesini sağlamak için placement'a bir [yedek paywall](capacitor-use-fallback-paywalls) yapılandırın. ## Tam örnek \{#complete-example\} `onAppleAdsAttribution`, Apple Ads attribution uygulandığında çözümlenir ya da `timeoutMs` süresinde reddedilir. Aşağıdaki kullanımda paywall hemen yüklenir, ardından attribution geldiğinde yeniden getirilir — Apple Ads kullanıcıları hedeflenmiş paywalli görür; attribution hiç gelmezse ilk paywall geçerli kalır: ```typescript const APPLE_ADS_SOURCE = 'apple_search_ads'; const placementId = 'YOUR_PLACEMENT_ID'; function hasAppleAdsAttribution(profile: AdaptyProfile): boolean { return profile.appliedAttributionSources?.includes(APPLE_ADS_SOURCE) ?? false; } /** * Resolves once Apple Ads attribution is applied to the profile. * Rejects with a timeout error if attribution never arrives within `timeoutMs`. * Call after `adapty.activate()`. */ export function onAppleAdsAttribution(timeoutMs: number): Promise<void> { return new Promise((resolve, reject) => { let timer: ReturnType<typeof setTimeout> | undefined; let handle: { remove: () => void } | undefined; const stop = () => { clearTimeout(timer); handle?.remove(); }; adapty .addListener('onLatestProfileLoad', ({ profile }) => { if (!hasAppleAdsAttribution(profile)) return; stop(); resolve(); }) .then(listener => { handle = listener; }); timer = setTimeout(() => { stop(); reject(new Error(`Apple Ads attribution timed out after ${timeoutMs}ms`)); }, timeoutMs); }); } let flow = await adapty.getFlow({ placementId }); onAppleAdsAttribution(30_000) .then(() => adapty.getFlow({ placementId })) .then(updated => { flow = updated; }) .catch(() => { console.log('Apple Ads attribution or loading failed'); }); ``` İlk başlatmada, Apple Ads kullanıcısı varsayılan paywallı kısaca görür ve ardından yenisiyle değiştirilir. Paywallları Paywall Builder ile sunuyorsanız, yeniden sunmanın kabul edilebilir olup olmadığına karar verin ya da güncellemeyi yalnızca paywall gösterilmeden önce uygulayın. `timeoutMs` değerini ne kadar süre dinlemeye hazır olduğunuza göre ayarlayın — gelmekte olan attribution genellikle başlatmanın birkaç saniyesi içinde ulaşır. Uygulamanız halihazırda başka amaçlarla `onLatestProfileLoad` dinliyorsa (örneğin, [abonelik durumunu kontrol etmek](capacitor-check-subscription-status#listen-to-subscription-updates) için), herhangi bir değişiklik yapmanıza gerek yok. `adapty.addListener` birden fazla bağımsız dinleyiciyi destekler; bu nedenle kendi dinleyicisi, diğerlerini etkilemeden eklenir. --- # File: capacitor-test --- --- title: "Capacitor SDK'da Test Et ve Yayınla" description: "Adapty SDK ile Capacitor uygulamanızı nasıl test edeceğinizi ve yayınlayacağınızı öğrenin." --- Adapty SDK'yı Capacitor uygulamanıza zaten entegre ettiyseniz, her şeyin doğru kurulduğunu ve satın almaların hem iOS hem de Android platformlarında beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunun hem de Apple'ın sandbox ortamı ve Google Play'in test ortamıyla gerçek satın alma akışının test edilmesini kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almalarınızı kapsamlı şekilde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayın için hazırlanın \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesi](release-checklist)'ni takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'ye bildiriliyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanıyor --- # File: kids-mode-capacitor --- --- title: "Capacitor SDK'da Kids Mode" description: "Apple ve Google politikalarına uyum için Kids Mode'u kolayca etkinleştirin. Capacitor SDK'da IDFA, GAID veya reklam verisi toplanmaz." --- Capacitor uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) ve [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikaları karşılayacak ve uygulama mağazası incelemelerinden geçecek şekilde yapılandırabilirsiniz. ## Neler gerekli? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Reklam Kimliği (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunların yanı sıra, müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `<Ad.Soyad>` formatındaki kullanıcı kimlikleri, e-posta kullanımı gibi, kesinlikle kişisel veri toplama olarak değerlendirilir. Kids Mode için en iyi uygulama, uyumu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (ör. hashlenmiş kimlikler veya cihaz tarafından üretilen UUID'ler) kullanmaktır. ## Kids Mode'u Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde yapılacak güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) bölümüne gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için kullanıcının IDFA, GAID ve IP adresi toplamasını devre dışı bırakın: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // Disable IP address collection ipAddressCollectionDisabled: true, // Disable IDFA collection on iOS ios: { idfaCollectionDisabled: true }, // Disable Google Advertising ID collection on Android android: { adIdCollectionDisabled: true } } }); console.log('Adapty activated with Kids Mode enabled'); } catch (error) { console.error('Failed to activate Adapty with Kids Mode:', error); } ``` ### Platforma Özgü Yapılandırmalar \{#platform-specific-configurations\} #### iOS \{#ios\} <SDKv4> IDFA koleksiyonu kodda devre dışı bırakılmış olsa bile (yukarıda), derlemeniz `AdSupport` ve `AppTrackingTransparency` framework'lerini hâlâ içerir. App Store Çocuklar Kategorisi bunlara izin vermez. v4 SDK, yerel iOS SDK'yı Swift Package Manager aracılığıyla yüklediğinden, bu framework'leri kaldırmak için bir Podfile adımı da yoktur. Apple'ın gereksinimlerine uymak için, SDK ile birlikte gelen `adapty-kids-mode` komutunu uygulamanızın `postinstall` betiğine ekleyin. Bu komut, SDK'nın `KidsMode` özelliğini etkinleştirerek söz konusu kodun derleme dışında bırakılmasını sağlar. Komut, her kurulumda yeniden uygulanır: ```json showLineNumbers title="package.json" { "scripts": { "postinstall": "adapty-kids-mode" } } ``` Ardından iOS paketlerini yeniden yükleyin ve çözümleyin, ardından **Xcode 26** veya sonraki bir sürümle derleyin: ```sh showLineNumbers title="Shell" npm install npx cap sync ios ``` Kids Mode'u kapatmak için `adapty-kids-mode disable` komutunu çalıştırın ve tekrar senkronize edin. </SDKv4> <SDKv3> iOS için CocoaPods kullanıyorsanız, Kids Mode'u native düzeyde de etkinleştirebilirsiniz: 1. Podfile'ınızı güncelleyin: - Eğer `post_install` bölümünüz **yoksa**, aşağıdaki kod bloğunun tamamını ekleyin. - Eğer `post_install` bölümünüz **varsa**, vurgulanan satırları mevcut bölümle birleştirin. ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. Değişiklikleri uygulamak için aşağıdaki komutu çalıştırın: ```sh showLineNumbers title="Shell" pod install ``` </SDKv3> #### Android: reklam kimliği iznini kaldırma \{#android-remove-the-advertising-id-permission\} `adIdCollectionDisabled: true` ayarı (yukarıda) Adapty'nin reklam kimliğini toplamasını durdurur, ancak SDK yine de `AD_ID` iznini bildirir. Uygulamanız **yalnızca** çocuklara yönelikse ve Android 13 (API 33) veya üzerini hedefliyorsa, Google Play bu izni talep etmenizi dahi yasaklar. `<manifest>` öğenize iki ekleme yapın: 1. `tools` isim alanını tanımlayın (Capacitor'ın varsayılan manifest dosyası bunu içermez). 2. `AD_ID` iznini kaldırmak için `tools:node="remove"` özelliğiyle bir `<uses-permission>` girişi ekleyin. ```xml showLineNumbers title="android/app/src/main/AndroidManifest.xml" <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" /> </manifest> ``` ## Sonraki adımlar \{#next-steps\} Kids Mode'u etkinleştirdikten sonra şunları yapmayı unutmayın: 1. Tüm işlevlerin doğru çalıştığından emin olmak için uygulamanızı kapsamlı şekilde test edin 2. Devre dışı bırakılan veri toplamayı yansıtmak için uygulamanızın gizlilik politikasını güncelleyin 3. Kids Mode uyumluluğuna ilişkin açık belgelerle uygulamanızı incelemeye gönderin Platforma özgü gereksinimler hakkında daha fazla bilgi için: - Ek iOS yapılandırma ayrıntıları için [iOS SDK'da Kids Mode](kids-mode) - Ek Android yapılandırma ayrıntıları için [Android SDK'da Kids Mode](kids-mode-android) --- # File: capacitor-reference --- --- title: "Referans" description: "Adapty Capacitor SDK için referans dokümantasyonu." --- Bu sayfa, Adapty Capacitor SDK için referans dokümantasyonu içerir. İhtiyacınız olan konuyu seçin: - **[SDK modelleri](https://capacitor.adapty.io/)** - SDK tarafından kullanılan veri modelleri ve yapıları - **[Hataları yönetme](capacitor-handle-errors)** - Hata yönetimi ve sorun giderme --- # File: capacitor-handle-errors --- --- title: "Capacitor SDK'da hataları yönetin" description: "Capacitor SDK'da hataları yönetin." --- SDK tarafından döndürülen her hata bir `AdaptyError` örneğidir. İşte bir örnek: :::tip **Hata ayıklamadan önce ayrıntılı logları etkinleştirin.** Çoğu `AdaptyError`, altta yatan bir StoreKit, Play Billing, ağ veya backend hatasını sarmalayan bir yapıya sahiptir. Ayrıntılı loglar açıkken (`adapty.setLogLevel({ logLevel: 'verbose' })` — bkz. [Loglama](sdk-installation-capacitor#logging)), sarmalanan hata konsola yazdırılır ve bu genellikle gerçek nedeni gösterir. `AdaptyError` üzerindeki `detail` özelliği log düzeyinden bağımsız olarak doldurulur — ayrıntılı loglar onu yalnızca konsolda görünür kılar. ::: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product }); // Handle purchase result if (result.type === 'success') { console.log('Purchase successful:', result.profile); } else if (result.type === 'user_cancelled') { console.log('User cancelled the purchase'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { if (error instanceof AdaptyError) { console.error('Adapty error:', error.adaptyCode, error.localizedDescription); // Handle specific error codes switch (error.adaptyCode) { case ErrorCodeName.cantMakePayments: console.log('In-app purchases are not allowed on this device'); break; case ErrorCodeName.notActivated: console.log('Adapty SDK is not activated'); break; case ErrorCodeName.productPurchaseFailed: console.log('Purchase failed:', error.detail); break; default: console.log('Other error occurred:', error.detail); } } else { console.error('Non-Adapty error:', error); } } ``` ## Hata Özellikleri \{#error-properties\} `AdaptyError` sınıfı aşağıdaki özellikleri sağlar: | Özellik | Tür | Açıklama | |---------|-----|----------| | `adaptyCode` | `number` | Sayısal hata kodu (ör. `1003`, cantMakePayments için) | | `localizedDescription` | `string` | Kullanıcı dostu hata mesajı | | `detail` | `string \| undefined` | Ek hata ayrıntıları (isteğe bağlı) | | `message` | `string` | Kod ve açıklamayı içeren tam hata mesajı | ## Hata Kodları \{#error-codes\} SDK, hata kodlarıyla çalışmak için sabitler ve yardımcı araçlar sunar: ### ErrorCodeName Sabiti \{#errorcodename-constant\} Dize tanımlayıcılarını sayısal kodlarla eşleştirir: ```typescript ErrorCodeName.cantMakePayments // 1003 ErrorCodeName.notActivated // 2002 ErrorCodeName.networkFailed // 2005 ``` ### ErrorCode Sabiti \{#errorcode-constant\} Sayısal kodları dize tanımlayıcılarıyla eşleştirir: ```typescript ErrorCode[1003] // 'cantMakePayments' ErrorCode[2002] // 'notActivated' ErrorCode[2005] // 'networkFailed' ``` ### Yardımcı Fonksiyonlar \{#helper-functions\} ```typescript // Get numeric code from string name: getErrorCode('cantMakePayments') // 1003 // Get string name from numeric code: getErrorPrompt(1003) // 'cantMakePayments' ``` ### Hata Kodlarını Karşılaştırma \{#comparing-error-codes\} **Önemli:** `error.adaptyCode` bir **sayı** olduğundan, doğrudan sayısal kodlarla karşılaştırın: ```typescript // Option 1: Use ErrorCodeName constant (recommended) ✅ if (error.adaptyCode === ErrorCodeName.cantMakePayments) { console.log('Cannot make payments'); } // Option 2: Compare with numeric literal ✅ if (error.adaptyCode === 1003) { console.log('Cannot make payments'); } // NOT like this ❌ - compares number to string and will never match if (error.adaptyCode === ErrorCode[1003]) { } ``` ## Global Hata Yöneticisi \{#global-error-handler\} Tüm Adapty hatalarını yakalamak için global bir hata yöneticisi kurabilirsiniz: ```typescript showLineNumbers // Set up global error handler AdaptyError.onError = (error: AdaptyError) => { console.error('Global Adapty error:', { code: error.adaptyCode, message: error.localizedDescription, detail: error.detail }); // Handle specific error types globally if (error.adaptyCode === ErrorCodeName.notActivated) { // SDK not activated - maybe retry activation console.log('SDK not activated, attempting to reactivate...'); } }; ``` ## Yaygın Hata Yönetimi Kalıpları \{#common-error-handling-patterns\} ### Satın Alma Hatalarını Yönetme \{#handle-purchase-errors\} ```typescript showLineNumbers async function handlePurchase(product: AdaptyPaywallProduct) { try { const result = await adapty.makePurchase({ product }); if (result.type === 'success') { console.log('Purchase successful:', result.profile); } else if (result.type === 'user_cancelled') { console.log('User cancelled the purchase'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { if (error instanceof AdaptyError) { switch (error.adaptyCode) { case ErrorCodeName.cantMakePayments: console.log('In-app purchases not allowed'); break; case ErrorCodeName.productPurchaseFailed: console.log('Purchase failed:', error.detail); break; default: console.error('Purchase error:', error.localizedDescription); } } } } ``` ### Ağ Hatalarını Yönetme \{#handle-network-errors\} ```typescript showLineNumbers async function fetchFlow(placementId: string) { try { const flow = await adapty.getFlow({ placementId }); return flow; } catch (error) { if (error instanceof AdaptyError) { switch (error.adaptyCode) { case ErrorCodeName.networkFailed: console.log('Network error, retrying...'); // Implement retry logic break; case ErrorCodeName.serverError: console.log('Server error:', error.detail); break; case ErrorCodeName.notActivated: console.log('SDK not activated'); break; default: console.error('Paywall fetch error:', error.localizedDescription); } } throw error; } } ``` ## Sistem StoreKit Kodları \{#system-storekit-codes\} | Hata | Kod | Açıklama | |-----|----|-----------| | unknown | 0 | Bilinmeyen veya beklenmedik bir hata oluştuğunu belirtir. | | clientInvalid | 1 | İstemcinin denenen işlemi gerçekleştirmesine izin verilmediğini belirtir. | | paymentCancelled | 2 | <p>Kullanıcının ödeme isteğini iptal ettiğini belirtir.</p><p>Herhangi bir işlem yapmanız gerekmez; ancak iş mantığı açısından kullanıcıya indirim teklif edebilir veya daha sonra hatırlatabilirsiniz.</p> | | paymentInvalid | 3 | Ödeme parametrelerinden birinin mağaza tarafından tanınmadığını belirtir. | | paymentNotAllowed | 4 | <p>Kullanıcının ödeme yapmasına izin verilmediğini belirtir. Olası nedenler:</p><p></p><p>- Kullanıcının bulunduğu ülkede ödemeler desteklenmiyor.</p><p>- Kullanıcı reşit değil.</p> | | storeProductNotAvailable | 5 | İstenen ürünün App Store'da mevcut olmadığını belirtir. Ürünün kullanılan ülke için geçerli olduğundan emin olun. | | cloudServicePermissionDenied | 6 | Kullanıcının Cloud servisi bilgilerine erişime izin vermediğini belirtir. | | cloudServiceNetworkConnectionFailed | 7 | Cihazın ağa bağlanamadığını belirtir. | | cloudServiceRevoked | 8 | Kullanıcının bu cloud servisini kullanma iznini iptal ettiğini belirtir. | | privacyAcknowledgementRequired | 9 | Kullanıcının mağaza gizlilik politikasını henüz onaylamadığını belirtir. | | unauthorizedRequestData | 10 | İsteğin hatalı oluşturulduğunu belirtir. | | invalidOfferIdentifier | 11 | <p>Teklif tanımlayıcısı geçerli değil. Olası nedenler:</p><p></p><p>- App Store'da bu tanımlayıcıyla bir teklif oluşturmadınız.</p><p>- Teklifi iptal ettiniz.</p><p>- Teklif ID'sini yanlış girdiniz.</p> | | invalidSignature | 12 | Ödeme indirimindeki imzanın geçerli olmadığını belirtir. **In-app purchase Key ID** alanını doldurduğunuzdan ve **In-App Purchase Private Key** dosyasını yüklediğinizden emin olun. Ayrıntılar için [App Store entegrasyonunu yapılandırma](app-store-connection-configuration) konusuna bakın. | | missingOfferParams | 13 | <p>Bu hata, Adapty entegrasyonuyla veya tekliflerle ilgili sorunlara işaret eder.</p><p>Nasıl yapılandırılacağı hakkında ayrıntılar için [App Store entegrasyonunu yapılandırma](app-store-connection-configuration) ve [Teklifler](offers) konularına bakın.</p> | | invalidOfferPrice | 14 | Mağazada belirlediğiniz fiyatın artık geçerli olmadığını belirtir. Teklifler her zaman indirimli bir fiyatı temsil etmelidir. | ## Özel Android Kodları \{#custom-android-codes\} | Hata | Kod | Açıklama | |-----|----|-----------| | adaptyNotInitialized | 20 | Adapty SDK'yı `Adapty.activate` metoduyla düzgün şekilde yapılandırmanız gerekiyor. [React Native için](sdk-installation-reactnative) nasıl yapılacağını öğrenin. | | productNotFound | 22 | Satın alınmak istenen ürünün mağazada mevcut olmadığını belirtir. | | invalidJson | 23 | Paywall JSON'ı geçerli değil. Adapty Kontrol Paneli'nde düzeltin. Nasıl düzeltileceği hakkında ayrıntılar için [Paywall'u remote config ile özelleştirme](customize-paywall-with-remote-config) konusuna bakın. | | currentSubscriptionToUpdateNotFoundInHistory | 24 | Yenilenmesi gereken orijinal abonelik geçmişte bulunamadı. | | pendingPurchase | 25 | Satın alma durumunun tamamlanmış değil, beklemede olduğunu belirtir. Ayrıntılar için Android Developer belgelerindeki [Bekleyen işlemleri yönetme](https://developer.android.com/google/play/billing/integrate#pending) sayfasına bakın. | | billingServiceTimeout | 97 | Google Play'in yanıt veremeden önce isteğin maksimum zaman aşımına ulaştığını belirtir. Bu durum, örneğin Play Billing Library çağrısının istenen işlemi yürütmesinde gecikme yaşanmasından kaynaklanabilir. | | featureNotSupported | 98 | İstenen özellik, mevcut cihazda Play Store tarafından desteklenmiyor. | | billingServiceDisconnected | 99 | Bu kritik hata, istemci uygulamanın `BillingClient` aracılığıyla Google Play Store servisine olan bağlantısının kesildiğini belirtir. | | billingServiceUnavailable | 102 | Bu geçici hata, Google Play Billing servisinin şu anda kullanılamadığını belirtir. Çoğu durumda bu, istemci cihaz ile Google Play Billing servisleri arasında herhangi bir noktada ağ bağlantısı sorunu olduğu anlamına gelir. | | billingUnavailable | 103 | <p>Satın alma işlemi sırasında kullanıcı kaynaklı bir faturalama hatası oluştuğunu belirtir. Bu hatanın oluşabileceği durumlar şunlardır:</p><p></p><p>1\. Kullanıcının cihazındaki Play Store uygulaması güncel değil.</p><p>2. Kullanıcı desteklenmeyen bir ülkede.</p><p>3. Kullanıcı bir kurumsal hesap kullanıyor ve kurumsal yönetici satın alma işlemlerini devre dışı bırakmış.</p><p>4. Google Play, kullanıcının ödeme yöntemini tahsil edemiyor. Örneğin, kullanıcının kredi kartı süresi dolmuş olabilir.</p><p>5. Kullanıcı Play Store uygulamasında oturum açmamış.</p> | | developerError | 105 | Bu kritik hata, bir API'nin yanlış kullanıldığını belirtir. | | billingError | 106 | Bu kritik hata, Google Play'in kendi içinde bir sorun olduğunu belirtir. | | itemAlreadyOwned | 107 | Consumable ürün zaten satın alınmış. | | itemNotOwned | 108 | İstenen işlemin öğe üzerinde başarısız olduğunu belirtir. | ## Özel StoreKit Kodları \{#custom-storekit-codes\} | Hata | Kod | Açıklama | |-----|----|-----------| | noProductIDsFound | 1000 | <p>Paywall'daki ürünlerin hiçbirinin mağazada mevcut olmadığını belirtir.</p><p>Bu hatayla karşılaşıyorsanız çözmek için aşağıdaki adımları izleyin:</p><p></p><p>1. Tüm ürünlerin Adapty Kontrol Paneli'ne eklenip eklenmediğini kontrol edin.</p><p>2. Uygulamanızın Bundle ID'sinin Apple Connect'tekiyle eşleştiğinden emin olun.</p><p>3. Uygulama mağazalarındaki ürün tanımlayıcılarının Kontrol Paneli'ne eklediğinizle eşleştiğini doğrulayın. Tanımlayıcıların, mağazada zaten dahil değilse Bundle ID içermemesi gerektiğine dikkat edin.</p><p>4. Apple vergi ayarlarında uygulamanın ücretli durumunun aktif olduğunu onaylayın. Vergi bilgilerinizin güncel ve sertifikalarınızın geçerli olduğundan emin olun.</p><p>5. Uygulamanın monetizasyona uygun olabilmesi için bir banka hesabının bağlı olup olmadığını kontrol edin.</p><p>6. Ürünlerin tüm bölgelerde kullanılabilir olup olmadığını kontrol edin. Ayrıca ürünlerinizin **"Ready to Submit"** durumunda olduğundan emin olun.</p> | | productRequestFailed | 1002 | <p>Şu anda mevcut ürünler alınamıyor. Olası neden:</p><p></p><p>- Henüz önbellek oluşturulmamış ve aynı zamanda internet bağlantısı yok.</p> | | cantMakePayments | 1003 | Bu cihazda Uygulama İçi Satın Almalara izin verilmiyor. | | noPurchasesToRestore | 1004 | Google Play'in geri yüklenecek satın alma bulamadığını belirtir. | | cantReadReceipt | 1005 | <p>Cihazda geçerli bir makbuz yok. Bu durum sandbox testleri sırasında sorun oluşturabilir.</p><p>Herhangi bir işlem yapmanız gerekmez; ancak iş mantığı açısından kullanıcıya indirim teklif edebilir veya daha sonra hatırlatabilirsiniz.</p> | | productPurchaseFailed | 1006 | Ürün satın alımı başarısız oldu. Bu hata, altta yatan bir StoreKit hatasını sarmalamaktadır — gerçek nedeni öğrenmek için sarmalanan hatayı okuyun (veya konsolda görmek için ayrıntılı logları etkinleştirin). Sarmalanan hata genellikle yukarıdaki tablodaki 0–14 arasındaki StoreKit kodlarından biridir; en yaygın olanları `paymentCancelled`, `paymentInvalid`, `paymentNotAllowed` veya `invalidOfferPrice`'tır. Belirli bir neden tespit edemiyorsanız yeni bir [sandbox profili](test-purchases-in-sandbox) deneyin; sorun devam ederse Apple desteğiyle iletişime geçin. | | refreshReceiptFailed | 1010 | Makbuzun alınamadığını belirtir. Yalnızca StoreKit 1 için geçerlidir. | | receiveRestoredTransactionsFailed | 1011 | Satın alma geri yükleme başarısız oldu. | ## Özel Ağ Kodları \{#custom-network-codes\} | Hata | Kod | Açıklama | | :------------------- | :--- | :----------------------------------------------------------- | | notActivated | 2002 | Adapty SDK'yı `Adapty.activate` metoduyla düzgün şekilde yapılandırmanız gerekiyor. [React Native için](sdk-installation-reactnative) nasıl yapılacağını öğrenin. | | badRequest | 2003 | Hatalı istek. | | serverError | 2004 | Sunucu hatası. | | networkFailed | 2005 | Ağ isteği başarısız oldu. | | decodingFailed | 2006 | Yanıt kod çözme işleminin başarısız olduğunu belirtir. | | encodingFailed | 2009 | İstek kodlama işleminin başarısız olduğunu belirtir. | | analyticsDisabled | 3000 | Analytics olaylarını işleyemiyoruz çünkü bu özelliği devre dışı bıraktınız. Ayrıntılar için [Analytics entegrasyonu](analytics-integration) konusuna bakın. | | wrongParam | 3001 | Bazı parametrelerinizin hatalı olduğunu belirtir: boş bırakılamayacak alanlar boş bırakılmış ya da yanlış türde değer girilmiş olabilir. | | activateOnceError | 3005 | `.activate` metodu birden fazla kez çağrılamaz. | | profileWasChanged | 3006 | İşlem sırasında kullanıcı profili değiştirildi. | | fetchTimeoutError | 3101 | Paywall'un belirlenen süre içinde alınamadığını belirtir. Bu durumu önlemek için [yerel yedekler ayarlayın](fetch-paywalls-and-products). | | operationInterrupted | 9000 | Bu işlem sistem tarafından kesildi. | --- # File: capacitor-sdk-migration-guides --- --- title: "Capacitor SDK Geçiş Kılavuzları" description: "Adapty Capacitor SDK sürümleri için geçiş kılavuzları." --- Bu sayfa, Adapty Capacitor SDK için tüm geçiş kılavuzlarını içermektedir. Ayrıntılı talimatlar için geçmek istediğiniz sürümü seçin: - **[v4.0'a geçiş (beta)](migration-to-capacitor-sdk-v4)** - [**v3.16'ya geçiş**](migration-to-capacitor-316) --- # File: migration-to-capacitor-sdk-v4 --- --- title: "Adapty Capacitor SDK'yı v. 4.0'a Geçirme" description: "Adapty Capacitor SDK v4.0'a (beta) geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty Capacitor SDK 4.0 (beta), flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı Başvuru \{#quick-reference\} | v3 | v4 | |---|---| | `adapty.getPaywall({ placementId, locale?, params? })` | `adapty.getFlow({ placementId, params? })` | | `adapty.getPaywallForDefaultAudience({ placementId, locale?, params? })` | `adapty.getFlowForDefaultAudience({ placementId, params? })` | | `adapty.getPaywallProducts({ paywall })` | `adapty.getPaywallProducts({ flow })` | | `adapty.logShowPaywall({ paywall })` | `adapty.logShowFlow({ flow })` | | `AdaptyPaywall` (tür) | `AdaptyFlow` + `AdaptyFlowPaywall` | | `createPaywallView(paywall, params?)` | `createFlowView(flow, params?)` | | `PaywallViewController` | `FlowViewController` | | `EventHandlers` (tür) | `FlowEventHandlers` | | `CreatePaywallViewParamsInput` | `CreateFlowViewParamsInput` | | `onRenderingFailed` | `onError` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a ait olmaya devam eder ve `getPaywallProducts` de adını korur, artık bir `AdaptyFlow` alır. `getFlow` ve `getFlowForDefaultAudience` metodları artık `locale` parametresi almaz. Satın alma ve profil API'leri (`makePurchase`, `restorePurchases`, `getProfile`, `identify`, `updateProfile`) ve `setFallback` aracılığıyla yedekler değişmeden kalır. `present`, `dismiss`, `setEventHandlers` ve `showDialog` gibi görünüm metodları ile `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` ve `onAndroidSystemBack` olay işleyicileri v3'tekiyle aynı adları korur. Onboarding metodları çalışmaya devam eder ancak kullanımdan kaldırılmıştır — bkz. [Onboarding API kullanımdan kaldırma](#onboarding-api-deprecation). Bazı varsayılan davranışlar değişti — bkz. [Varsayılan davranış değişiklikleri](#default-behavior-changes). ## Minimum versions \{#minimum-versions\} Çalışma zamanı gereksinimleri v3.16+'dan bu yana değişmedi: **iOS 15.0**, **Android minSdk 24** ve **Capacitor 8**. Deployment target ayarlarında herhangi bir değişiklik gerekmez. Bir yeni derleme gereksinimi var: **Xcode 26 veya üzeri** — bu sürümle birlikte gelen yerel Adapty iOS SDK 4.0.0-beta.2, Swift tools 6.2 kullanıyor. v4, yerel Adapty SDK'larından iOS 4.0.0-beta.2 ve Android BOM 4.0.0-beta.1'i içeriyor. ## Kurulum \{#installation\} ### Paketi güncelleyin \{#update-the-package\} v4.0 bir ön sürüm olduğundan, tam sürümü sabitleyin — npm, şapka/tilde aralıklarıyla ön sürüm sürümlerini seçmez: ```bash showLineNumbers npm install @adapty/capacitor@4.0.0-beta.2 ``` Ardından yerel projeleri senkronize edin: ```bash showLineNumbers npx cap sync ``` ### iOS: Yalnızca Swift Package Manager [CocoaPods'ın spec repo'su Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/); bu nedenle v4 itibarıyla `AdaptyCapacitor.podspec` kaldırılmıştır ve SDK, iOS'ta **yalnızca Swift Package Manager (SPM)** üzerinden kurulmaktadır. Uygulamanızın iOS projesinin Capacitor'ın SPM entegrasyonunu kullanması gerekir: - Yeni uygulamalar için iOS platformunu SPM paket yöneticisiyle ekleyin: ```bash showLineNumbers npx cap add ios --packagemanager SPM ``` - Mevcut CocoaPods tabanlı uygulamalar: [Capacitor'ın mevcut bir projede SPM kullanma kılavuzu](https://capacitorjs.com/docs/ios/spm#using-spm-in-an-existing-capacitor-project)nu izleyerek iOS projesini taşıyın. Tam kurulum için [Adapty SDK'yı Yükle](sdk-installation-capacitor) sayfasına bakın. ## Flow'ları Getirme \{#fetching-flows\} ### getPaywall → getFlow Döndürülen tür `AdaptyPaywall`'dan `AdaptyFlow`'a değişiyor ve `locale` seçeneği kaldırılıyor — bir flow render ettiğinizde locale otomatik olarak çözümlenir; özel paywalllar için tüm locale'ler `flow.remoteConfigs` içinde döndürülür: ```diff showLineNumbers - const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en' }); + const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); ``` `getPaywallForDefaultAudience` de aynı şekilde yeniden adlandırılıyor: ```diff showLineNumbers - const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en' }); + const flow = await adapty.getFlowForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID' }); ``` ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` adını korur ancak artık bir `AdaptyFlow` alır: ```diff showLineNumbers - const products = await adapty.getPaywallProducts({ paywall }); + const products = await adapty.getPaywallProducts({ flow }); ``` ## Veri modeli \{#data-model\} `getFlow`, `AdaptyPaywall` yerine bir `AdaptyFlow` döndürür ve nesne yapısı değişti: | v3 `AdaptyPaywall` alanı | v4 `AdaptyFlow` alanı | İşlem | |---|---|---| | `remoteConfig?` (tekil) | `remoteConfigs?: AdaptyRemoteConfig[]` (dizi) | Bir flow, yapılandırılmış her dil için bir remote config taşır. Kullanıcıyla eşleşeni okuyun: `flow.remoteConfigs?.find((c) => c.lang === 'en')`. | | `products` | `flow.paywalls[i].productIdentifiers` | Ürün tanımlayıcıları artık flow üzerinde değil, her flow varyasyonunda yer alır. | | `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Flow'dan her paywall varyasyonuna taşındı. | | `version?: number` | `flowVersionId?: string` | Yeniden adlandırıldı ve tür `number`'dan `string`'e değişti. | | `hasViewConfiguration` | kaldırıldı | `hasViewConfiguration` kontrolünü kodunuzdan kaldırın — `createFlowView` artık bunun yerine hata fırlatır (bkz. [Flow'ları görüntüleme](#displaying-flows)). | | `requestLocale` | kaldırıldı | Locale artık modelin bir parçası değildir. | | _(yeni)_ | `paywalls: AdaptyFlowPaywall[]` | Her giriş, flow'daki bir paywall varyasyonudur. | | _(yeni)_ | `responseCreatedAt: number` | Sunucu yanıt zaman damgası, milisaniye cinsinden. | `hasViewConfiguration` ve `requestLocale`, `AdaptyOnboarding` üzerinde kalmaya devam eder — yalnızca flow modeli bunları kaldırır. Ürün tanımlayıcıları flow'dan her varyasyona taşındı: ```diff showLineNumbers - const ids = paywall.products; + const ids = flow.paywalls[0].productIdentifiers; ``` ## Web paywall yöntemleri \{#web-paywall-methods\} `openWebPaywall` ve `createWebPaywallUrl` adlarını korur, ancak `paywallOrProduct` seçeneği artık `AdaptyPaywall` yerine `AdaptyFlowPaywall` (bir flow varyasyonu) alır. Yine de `AdaptyPaywallProduct` geçirebilirsiniz. İlk girişi okumadan önce `flow.paywalls` öğesinin boş olmadığını kontrol edin: ```diff showLineNumbers const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); - await adapty.openWebPaywall({ paywallOrProduct: paywall }); + await adapty.openWebPaywall({ paywallOrProduct: flow.paywalls[0] }); ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık bir `AdaptyFlow` alıyor. Olay hâlâ aynı varyasyon üzerinden kaydedildiği için mevcut dönüşüm hunisi ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder. ```diff showLineNumbers - await adapty.logShowPaywall({ paywall }); + await adapty.logShowFlow({ flow }); ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywallları görüntülerken bu metodu çağırmanıza gerek yoktur; Adapty bu görüntülemeleri otomatik olarak takip eder. ## Flow'ları Görüntüleme \{#displaying-flows\} ### createPaywallView → createFlowView Factory fonksiyonunu yeniden adlandırın ve `AdaptyFlow`'u geçirin. Döndürülen controller, `PaywallViewController`'dan `FlowViewController`'a yeniden adlandırıldı; ancak metodları (`present`, `dismiss`, `setEventHandlers`, `showDialog`) değişmedi. Params tipi `CreatePaywallViewParamsInput`'tan `CreateFlowViewParamsInput`'a yeniden adlandırıldı: ```diff showLineNumbers - import { createPaywallView } from '@adapty/capacitor'; + import { createFlowView } from '@adapty/capacitor'; - const view = await createPaywallView(paywall); + const view = await createFlowView(flow); await view.present(); ``` `createFlowView`, flow için yapılandırılmış bir view yoksa `AdaptyError` fırlatır — bu, v3'teki `hasViewConfiguration` kontrolünün yerini alır: ```diff showLineNumbers - if (paywall.hasViewConfiguration) { - const view = await createPaywallView(paywall); - await view.present(); - } + try { + const view = await createFlowView(flow); + await view.present(); + } catch (error) { + // the flow has no view configured, or view creation failed + } ``` :::note Bir flow view tek kullanımlıktır: `dismiss()` çağırdıktan sonra view yok edilir ve olay işleyicileri temizlenir; flow'u tekrar göstermek için `createFlowView`'ı yeniden çağırmanız gerekir. ::: ### Android güvenli alan dolguları \{#android-safe-area-paddings\} `CreateFlowViewParamsInput`, çalışma zamanında Android güvenli alan dolgularını kontrol eden yeni bir `enableSafeArea` parametresi ekler. Bu parametre, `android` anahtarı altında yer alır ve varsayılan değeri `true`'dur: ```typescript showLineNumbers const view = await createFlowView(flow, { android: { enableSafeArea: true }, }); ``` ## Olayları yönetme \{#handling-events\} Olay işleyici arayüzü `EventHandlers` yerine `FlowEventHandlers` olarak yeniden adlandırıldı ve bir callback yeniden adlandırıldı. Mevcut işleyici gövdelerinde kod değişikliği gerekmez — sadece yeniden adlandırın: ```diff showLineNumbers - onRenderingFailed: (error) => { /* … */ }, + onError: (error) => { /* … */ }, ``` Diğer tüm event handler'lar isimlerini korur. İki tanesi ayrıca ikinci bir argüman kazanır: `onPurchaseCompleted` artık `(purchaseResult, product)` ve `onPurchaseFailed` artık `(error, product)` şeklindedir; burada `product`, işleme dahil olan `AdaptyPaywallProduct`'tır. Tam liste için [Flow ve paywall event'lerini yönetme](capacitor-handling-events) sayfasına bakın. v4 ayrıca isteğe bağlı olarak etkinleştirebileceğiniz birkaç yeni özellik ekler: - `adapty.openWebUrl({ url, openIn })` ve `adapty.requestAppReview()` metodları — bunlar varsayılan `onUrlPress` ve `onRequestAppReview` işleyicilerini destekler; bu sayede URL'ler ve uygulama değerlendirme istemleri kutudan çıkar çıkmaz yerel olarak yönetilir. Bu işleyicileri geçersiz kıldığınızda doğrudan çağırın. - Flow'lar içinde Observer modu satın alma yönetimi, yeni `onObserverPurchaseInitiated` / `onObserverRestoreInitiated` işleyicileri aracılığıyla yapılır. Bkz. [Flow'ları Observer modunda sunma](capacitor-present-flows-in-observer-mode). ## Varsayılan davranış değişiklikleri \{#default-behavior-changes\} Bu değişiklikler derleme hatası oluşturmaz, bu nedenle çalışma zamanında test edin: - **`onAndroidSystemBack`**: Varsayılan davranış, görünümü kapatmaktan açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `true` döndürün. - **`onPurchaseCompleted`**: Varsayılan davranış, satın alma iptal edilmediği sürece görünümü kapatmaktan her zaman açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `purchaseResult.type !== 'user_cancelled'` döndürün. - **`onRestoreCompleted`**: Varsayılan davranış, başarılı bir geri yüklemenin ardından görünümü kapatmaktan açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `true` döndürün. - **`onUrlPress`**: Varsayılan artık URL'yi yerel katman aracılığıyla açıyor; kontrol panelindeki uygulama içi veya harici tarayıcı ayarına göre davranıyor. URL'leri kendiniz açmak için handler'ı geçersiz kılın. - **Görünümler tek kullanımlıktır**: `dismiss()` çağrıldıktan sonra görünüm yok edilir. Flow'u tekrar göstermek için `createFlowView`'ı yeniden çağırın. ## Kaldırılan API'ler \{#removed-apis\} ### Kaldırılan exportlar \{#removed-exports\} Bu semboller artık `@adapty/capacitor`'dan export edilmiyor. İlgili importları kaldırın: - **`AdaptyPaywall`**: Bunun yerine `AdaptyFlow` ve `AdaptyFlowPaywall` kullanın. - **`ProductReference`**: Bunun yerine `AdaptyProductIdentifier` kullanın; `flow.paywalls[i].productIdentifiers` üzerinden okuyun. - **`AdaptyPaywallBuilder`**: Kaldırıldı. Flow'lar ve paywall'lar artık native olarak render edilir. - **`AdaptyAndroidSubscriptionUpdateParameters`**: İç içe geçmiş `android` satın alma parametre yapısını kullanın (aşağıya bakın). ### activate: lockMethodsUntilReady `lockMethodsUntilReady` (v3'te zaten kullanımdan kaldırılmış ve işlevsiz hale getirilmişti) kaldırıldı. `activate` çağrınızdan bu parametreyi kaldırın — aksi hâlde artık derlenmez: ```diff showLineNumbers - await adapty.activate({ apiKey: 'PUBLIC_SDK_KEY', params: { lockMethodsUntilReady: true } }); + await adapty.activate({ apiKey: 'PUBLIC_SDK_KEY' }); ``` ### makePurchase: Android parametreleri \{#makepurchase-android-parameters\} `MakePurchaseParamsInput`'ın kullanımdan kaldırılmış düz Android yapısı kaldırıldı — yalnızca iç içe geçmiş form geçerlidir. Android satın alma parametrelerini `params: { android: { ... } }` içine taşıyın. Tam örnek için [Satın alma yapma](capacitor-making-purchases) sayfasına bakın. ## Onboarding API kullanımdan kaldırılması \{#onboarding-api-deprecation\} Eski onboarding API'si v4.0'da [Flow Builder](adapty-flow-builder) lehine kullanımdan kaldırıldı. Hâlâ çalışmaya devam etmektedir, ancak gelecekteki bir sürümde kaldırılacaktır; bu nedenle onboarding'lerinizi Flow Builder'a taşımayı planlayın. Kullanımdan kaldırılan semboller: `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView` ve `OnboardingViewController`. --- # File: migration-to-capacitor-316 --- --- title: "Adapty Capacitor SDK'sını v3.16'ya Geçir" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Capacitor SDK v3.16'ya geçin." --- Adapty SDK v3.16.0'dan itibaren Capacitor 8 gereklidir. Capacitor 7'ye ihtiyaç duyuyorsanız Adapty SDK v3.15'i kullanın. Capacitor SDK v3.16'ya yükseltmek için projenizin Capacitor 8 kullandığından emin olun. Hâlâ Capacitor 7 kullanıyorsanız iki seçeneğiniz var: 1. **Capacitor 8'e Yükseltin**: Projenizi güncellemek için [resmi Capacitor taşıma kılavuzunu](https://capacitorjs.com/docs/updating/8-0) takip edin, ardından Adapty SDK v3.16'yı yükleyin. 2. **Adapty SDK v3.15'te Kalın**: Capacitor 8'e yükseltmek mümkün değilse, Capacitor 7'yi destekleyen Adapty SDK v3.15'i kullanmaya devam edin. --- # End of Documentation _Generated on: 2026-07-24T13:02:34.287Z_ _Successfully processed: 45/45 files_ # FLUTTER - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.289Z Total files: 44 --- # File: sdk-installation-flutter --- --- title: "Flutter SDK'yı Yükleyin ve Yapılandırın" description: "Flutter için Adapty SDK'yı abonelik tabanlı uygulamalara adım adım yükleme rehberi." --- Adapty SDK, Flutter uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız bu modüle ihtiyaç duyarsınız. Paywall Builder, platformlar arası paywall'lar oluşturmayı kolaylaştıran, kod gerektirmeyen kullanıcı dostu bir araçtır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywall gösterme, satın alma yapma ve diğer temel işlevleri kapsayan tam kurulumu içeren [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) göz atın. ::: ## Gereksinimler \{#requirements\} Adapty SDK, iOS 13.0+ sürümünü destekler; ancak paywall builder ile oluşturulan paywallların düzgün çalışması için iOS 15.0+ gereklidir. [Flow Builder](adapty-flow-builder) desteği ekleyen Adapty Flutter SDK 4.0, minimum gereksinimleri **iOS 15.0+**, **Xcode 26+** ve **Flutter 3.32.0+** (Dart 3.8.0+) olarak yükseltmektedir. Kurulum ayrıntıları için aşağıdaki [Adapty SDK 4.0](#adapty-sdk-40-swift-package-manager) bölümüne bakın. :::info Adapty, Google Play Billing Library 8.x sürümüne kadar uyumludur. Varsayılan olarak Adapty, Google Play Billing Library v7.0.0 ile çalışır; ancak daha yeni bir sürümü zorlamak istiyorsanız [bağımlılığı manuel olarak ekleyebilirsiniz](https://developer.android.com/google/play/billing/integrate#dependency). ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleme \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Flutter.svg?style=flat&logo=flutter)](https://github.com/adaptyteam/AdaptySDK-Flutter/releases) :::important Aşağıdaki adımlar en son kararlı SDK'yı (3.x) yükler. [Flow Builder](adapty-flow-builder) için gerekli olan ve [hızlı başlangıç](flutter-quickstart-paywalls) kılavuzunda kullanılan v4'e ihtiyacınız varsa, bunun yerine aşağıdaki [Adapty SDK 4.0: Swift Package Manager](#adapty-sdk-40-swift-package-manager) bölümünü izleyin. ::: 1. Adapty'yi `pubspec.yaml` dosyanıza ekleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: ^<the latest SDK version> ``` 2. Bağımlılıkları yüklemek için aşağıdaki komutu çalıştırın: ```bash showLineNumbers title="Terminal" flutter pub get ``` 3. Adapty SDK'larını uygulamanıza dahil edin: ```dart showLineNumbers title="main.dart" import 'package:adapty_flutter/adapty_flutter.dart'; ``` ### Adapty SDK 4.0: Swift Package Manager Adapty Flutter SDK 4.0'ı — [Flow Builder](adapty-flow-builder) desteği ekleyen — `pubspec.yaml` dosyanıza ekleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: 4.0.0 ``` v4 ile birlikte, yerel iOS SDK'sı artık CocoaPods üzerinden dağıtılmamaktadır — eklenti bunu yalnızca **Swift Package Manager** aracılığıyla çeker ([CocoaPods'un spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). Flutter 3.32–3.43 kullanıyorsanız, Swift Package Manager desteğini bir kez etkinleştirin: ```bash showLineNumbers title="Terminal" flutter config --enable-swift-package-manager ``` Flutter 3.44 ve sonraki sürümlerde Swift Package Manager varsayılan olarak etkin olduğundan herhangi bir işlem yapmanıza gerek yoktur. v4'teki API değişiklikleri için [taşıma kılavuzuna](migration-to-flutter-sdk-v4) bakın. ## Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK, uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. ```dart showLineNumbers title="main.dart" void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override void initState() { _initializeAdapty(); super.initState(); } Future<void> _initializeAdapty() async { try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY'), ); } catch (e) { // handle the error } } Widget build(BuildContext context) { return Text("Hello"); } } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıralama için bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](flutter-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywalllar için hızlı başlangıç kılavuzuna](flutter-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ve [AdaptyUI modülünü yüklediyseniz](sdk-installation-flutter#install-adapty-sdk), AdaptyUI'ı da etkinleştirmeniz gerekir: :::note AdaptyUI ile ilgili bağımlılıklar, AdaptyUI etkinleştirilmiş olup olmadığından bağımsız olarak uygulamanıza bağlıdır. ::: :::important Kodunuzda, AdaptyUI'ı etkinleştirmeden önce önce çekirdek Adapty modülünü etkinleştirmeniz gerekir. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withActivateUI(true), // This automatically activates AdaptyUI ); ``` ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kayıt sistemini kurma \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri günlüğe kaydeder. Aşağıdaki seviyeler mevcuttur: | Seviye | Açıklama | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------- | | `AdaptyLogLevel.error` | Yalnızca hatalar loglanır. | | `AdaptyLogLevel.warn` | Kritik hatalara yol açmayan ancak dikkat edilmesi gereken hatalar ve SDK mesajları loglanır. | | `AdaptyLogLevel.info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır. Varsayılan değer. | | `AdaptyLogLevel.verbose` | Hata ayıklama sırasında işe yarayabilecek ek bilgiler (fonksiyon çağrıları, API sorguları vb.) loglanır. | | `AdaptyLogLevel.debug` | Hata ayıklama bilgileri loglanır. | Adapty'yi yapılandırmadan önce uygulamanızda log seviyesini ayarlayabilirsiniz: ```dart showLineNumbers title="main.dart" // Set log level before activation. // 'verbose' is recommended for development and the first production release await Adapty().setLogLevel(AdaptyLogLevel.verbose); // Or set it during configuration await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withLogLevel(AdaptyLogLevel.verbose), ); ``` ### Veri politikaları \{#data-policies\} Adapty, siz açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz. Ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşımını devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özellikler uygulamanız için gerekli olmadığında gereksiz veri toplamayı azaltmak amacıyla kullanabilirsiniz. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withIpAddressCollectionDisabled(true), ); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `appleIdfaCollectionDisabled` (iOS) veya `googleAdvertisingIdCollectionDisabled` (Android) parametresini `true` olarak ayarlayın. Varsayılan değer `false`'tur. App Store/Play Store politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak veya uygulamanız reklam kimliklerine dayalı attribution ya da analiz gerektirmiyorsa bu parametreyi kullanın. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleIdfaCollectionDisabled(true) // iOS ..withGoogleAdvertisingIdCollectionDisabled(true), // Android ); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlayın \{#set-up-media-cache-configuration-for-adaptyui\} Modül, Adapty SDK ile birlikte otomatik olarak etkinleştirilir. Paywall Builder kullanmıyorsanız ve AdaptyUI modülünü devre dışı bırakmak istiyorsanız, etkinleştirme sırasında `withActivateUI(false)` parametresini geçin. Varsayılan olarak, AdaptyUI performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) önbelleğe alır. Önbellek ayarlarını özel bir yapılandırma sağlayarak özelleştirebilirsiniz. Varsayılan önbellek sınırlarını geçersiz kılmak için `withMediaCacheConfiguration` kullanın. Bu isteğe bağlıdır; bu metodu çağırmazsanız varsayılan değerler kullanılır (100 MB disk boyutu, sınırsız bellek sayısı). Ancak yapılandırma nesnesini oluşturursanız tüm parametreleri zorunludur. ```dart showLineNumbers title="main.dart" final mediaCacheConfig = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit: 2147483647, // max int value diskStorageSizeLimit: 200 * 1024 * 1024, // 200 MB ); await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withMediaCacheConfiguration(mediaCacheConfig), ); ``` **Parametreler:** | Parametre | Varlık | Açıklama | |-------------------------|----------|-----------------------------------------------------------------------------| | memoryStorageTotalCostLimit | gerekli | Bellekteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer 100 MB'tır. | | memoryStorageCountLimit | gerekli | Bellek depolamasındaki öğe sayısı sınırı. Varsayılan değer maksimum int değeridir. | | diskStorageSizeLimit | gerekli | Diskteki dosya boyutu sınırı (bayt cinsinden). Varsayılan değer 100 MB'tır. | ### Yerel access level'ları etkinleştirme (Android) \{#enable-local-access-levels-android\} Varsayılan olarak, [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `withGoogleLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleLocalAccessLevelAllowed(true), ); ``` ### Yedekten geri yükleme sırasında verileri temizle \{#clear-data-on-backup-restore\} `appleClearDataOnBackup` değeri `true` olarak ayarlandığında, SDK uygulamanın iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywalllar dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla yeniden başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleClearDataOnBackup(true) // default – false ); ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Otomatik Yedekleme yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> #### Android'de başka bir uygulamadan geri döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} Satın alma akışını başlatan Activity, varsayılan olmayan bir `launchMode` kullanıyorsa, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan geri döndüğünde Android bu Activity'yi hatalı şekilde yeniden oluşturabilir ya da yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına veya iptal edilmiş gibi işlenmesine yol açabilir. Satın almaların düzgün çalışmasını sağlamak için, satın alma akışını başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın ve diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma akışını başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile SWIFT_VERSION geçersiz kılmasından kaynaklanan Swift 6 derleme hataları \{#swift-6-build-errors-caused-by-podfile-swift-version-override\} Flutter uygulamanızı iOS için derlerken Adapty pod hedeflerinde Swift 6 derleme hataları görebilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içindeki `@Sendable` uyumsuzlukları, Adapty türlerinde eksik `Sendable` uyumluluğu veya aktör yalıtım hataları yer alır. Adapty pod'ları `s.swift_version = '6.0'` olarak tanımlar ve derleme için Swift 6 gerektirir. Kendi uygulama kodunuz Swift 5'te kalabilir — yalnızca Adapty pod hedefleri (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`, `AdaptyLogger`, `AdaptyPlugin`) Swift 6 ile derlenmelidir. En yaygın neden, `ios/Podfile` dosyasındaki her pod hedefi için `SWIFT_VERSION` değerini yeniden yazan bir `post_install` hook'udur: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **Düzeltme**: Adapty pod hedeflerini geçersiz kılma işleminin dışında bırakın: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` Ardından `ios/` dizininden `pod install` komutunu çalıştırın ve yeniden derleyin. Doğrulamak için `ios/Pods/Pods.xcodeproj` dosyasını açın, `Adapty` pod hedefini seçin → **Build Settings** → **Swift Language Version**. Değerin **Swift 6** olması gerekir. --- # File: flutter-quickstart-paywalls --- --- title: "Flutter SDK ile Flow Builder kullanarak satın almaları etkinleştirin" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmek için hızlı başlangıç kılavuzu." --- Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – ürünleri kullanıcılara sunan ekran dizileri; no-code Flow Builder ile oluşturulur. SDK bunları `getFlow` aracılığıyla alır. Arayüzü kendi kodunuzla oluşturmayı tercih ederseniz bunun yerine paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](flutter-quickstart-manual). - [**Placement'lar**](placements) – flow'ları uygulamanızda nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Flow'ları kontrol panelindeki placement'lara bağlar, ardından kodunuzda placement ID'siyle talep edersiniz. Bu sayede A/B testi yürütmek ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın almaları etkinleştirmek için size üç yol sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder; karmaşık satın alma akışı, fiş doğrulama ve abonelik yönetimini arka planda halleder. | | Elle oluşturulan paywalllar | 🟡 Orta | Paywall arayüzünü uygulama kodunuzda kendiniz implement edersiniz, ancak ürün tekliflerinde esnekliği korumak için yine de Adapty'den flow nesnesini alırsınız. [Rehbere](flutter-quickstart-manual) bakın. | | Observer mode | 🔴 Zor | Zaten kendi satın alma altyapınız var ve bunu kullanmaya devam etmek istiyorsunuz. Observer mode'un Adapty'de bazı kısıtlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulmuş bir flow'un nasıl uygulanacağını göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, bkz. [Paywallları manuel olarak uygulama](flutter-quickstart-manual). ::: Adapty Flow Builder'da oluşturulmuş bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Görüntüleyin ve satın almaları Adapty yönetsin**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butonlara tıkladığında bağlantı açın veya flow'u kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Uygulamanızı Adapty Kontrol Paneli'nde [App Store](initial_ios) ve/veya [Google Play](initial-android) ile bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ona ürün ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'u ekleyin](create-placement). 5. Uygulama kodunuza [Adapty SDK'yı yükleyip etkinleştirin](sdk-installation-flutter). Bu kılavuz Adapty Flutter SDK v4 API'larını kullanır. :::tip Bu adımları tamamlamanın en hızlı yolu, [hızlı başlangıç kılavuzunu](quickstart) takip etmek veya [Developer CLI](developer-cli-quickstart) kullanarak paywall'lar ve placement'lar oluşturmaktır. ::: ## 1. Flow'u alın \{#1-get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturulmuş bir flow'u almak için şunları yapmanız gerekir: 1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın ve `hasViewConfiguration` özelliğini kontrol ederek bunun builder'da oluşturulup oluşturulmadığını doğrulayın. 2. `createFlowView` metodunu kullanarak flow view'ı oluşturun. View, flow'u görüntülemek için gereken UI öğelerini ve stil bilgilerini içerir. :::important Görünüm yapılandırmasını almak için builder'da **Show on device** geçişini açmanız gerekir. Aksi takdirde boş bir görünüm yapılandırması alırsınız ve flow görüntülenmez. ::: ```dart showLineNumbers try { // the requested flow final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final view = await AdaptyUI().createFlowView( flow: flow, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## 2. Flow'u görüntüleme \{#display-the-flow\} Artık flow view'a sahip olduğunuzda, onu görüntülemek için birkaç satır kod eklemeniz yeterli. Flow'u görüntülemek için `createFlowView` metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez gösterilebilir: kapatıldıktan sonra view bellekten silinir. Flow'u tekrar görüntülemeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createFlowView` metodunu bir kez daha çağırın. ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Bir flow'un nasıl görüntüleneceğine dair daha fazla ayrıntı için [kılavuzumuza](flutter-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#handle-button-actions\} Kullanıcılar flow içindeki butonlara tıkladığında Flutter SDK, satın alma işlemlerini, restorasyon işlemlerini, görünümü kapatmayı ve URL açmayı otomatik olarak yönetir. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve kodunuzda bu eylemleri yönetmeniz gerekir. Flow ekranındaki süreçleri kontrol etmek veya izlemek için `AdaptyUIFlowsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın. Bir kullanıcı bir eylem gerçekleştirdiğinde `flowViewDidPerformAction` tetiklenir ve uygulamanızın eylem ID'sine göre yanıt vermesi gerekir. Üç observer yöntemi **zorunludur**: `flowViewDidFinishPurchase`, `flowViewDidFinishRestore` ve `flowViewDidReceiveError` — bunlar olmadan sınıfınız derlenmez. :::tip Buton [aksiyonlarını](flutter-handle-paywall-actions) ve [olayları](flutter-handling-events) nasıl yöneteceğinize dair kılavuzlarımızı okuyun. ::: Gözlemciyi, bir widget'a bağlamak yerine bağımsız ve uzun ömürlü bir nesne olarak uygulayın. Uygulama genelinde tek bir global gözlemci slotu paylaşıldığından, bunu bir `State`'e bağlamak ekranı sızdırır (SDK ona güçlü bir referans tutar) ve bir sonraki ekran kendini kaydettiğinde sessizce değiştirilir. `extends` kullanmak aynı zamanda SDK'nın varsayılan davranışını miras aldığından, üç zorunlu metodun yanı sıra yalnızca önem verdiğiniz callback'leri override etmeniz yeterlidir. ```dart showLineNumbers title="Flutter" // A dedicated, long-lived handler for flow events. // It does NOT live inside a Widget/State, so it never leaks and is never // silently replaced when screens are pushed or popped. class FlowEventsHandler extends AdaptyUIFlowsEventsObserver { // A single, app-wide instance — same idiom as Adapty() and AdaptyUI(). static final FlowEventsHandler _instance = FlowEventsHandler._(); factory FlowEventsHandler() => _instance; FlowEventsHandler._(); // This method is called when user performs an action on the flow UI. // Overriding it replaces the default behavior (dismiss on close, open URLs), // so keep those cases if you want to preserve it. @override void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): // close the flow on the Android back button view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } // Required: decide what happens after a purchase finishes @override void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { if (purchaseResult is! AdaptyPurchaseResultUserCancelled) { view.dismiss(); } } // Required: dismiss the flow once a restore succeeds @override void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { view.dismiss(); } // Required: handle rendering and other view errors @override void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { print('Flow error: $error'); view.dismiss(); } } ``` İşleyiciyi uygulama başlangıcında, herhangi bir flow gösterilmeden önce **bir kez** kaydedin: ```dart showLineNumbers title="Flutter" AdaptyUI().setFlowsEventsObserver(FlowEventsHandler()); ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada görüntülenmeye hazır. Paywall üzerinden test satın alma işlemini tamamlayabildiğinizden emin olmak için satın almalarınızı [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da test edin. Şimdi, doğru kullanıcılara paywall gösterdiğinizden veya ücretli özelliklere erişim verdiğinizden emin olmak için [kullanıcıların access level'ını kontrol etmeniz](flutter-check-subscription-status) gerekiyor. ## Tam örnek \{#full-example\} Tüm bu adımların uygulamanızda birlikte nasıl entegre edileceğini aşağıda görebilirsiniz. ```dart void main() { // Register a single, long-lived observer once, before any flow is shown. // It is intentionally a plain object (NOT a Widget/State): its lifetime is the // whole app, so it never leaks and is never silently replaced when screens are // pushed or popped. AdaptyUI().setFlowsEventsObserver(FlowEventsHandler()); runApp(MaterialApp(home: FlowScreen())); } /// A dedicated handler for AdaptyUI flow events. /// /// It `extends` [AdaptyUIFlowsEventsObserver] (rather than being implemented /// by a `State`), which gives you two things for free: /// * the SDK's sensible defaults for optional callbacks, so besides the three /// required methods you only override what you actually care about; /// * a lifecycle that is independent of the widget tree — there is no strong /// reference back into a `Widget`, so nothing leaks and there is nothing to /// unregister. /// /// Every callback receives the [AdaptyUIFlowView] it relates to, so handling /// flow actions never requires a `BuildContext` or widget state. class FlowEventsHandler extends AdaptyUIFlowsEventsObserver { // A single, app-wide instance — same idiom as Adapty() and AdaptyUI(). static final FlowEventsHandler _instance = FlowEventsHandler._(); factory FlowEventsHandler() => _instance; FlowEventsHandler._(); // Called when the user performs an action on the flow UI. @override void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): // close the flow on the Android back button view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): // Open the URL natively, honoring the dashboard browser setting. AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } // Required: decide what happens after a purchase finishes. @override void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { if (purchaseResult is! AdaptyPurchaseResultUserCancelled) { view.dismiss(); } } // Required: dismiss the flow once a restore succeeds. @override void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { view.dismiss(); } // Required: handle rendering and other view errors. @override void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { print('Flow error: $error'); view.dismiss(); } } class FlowScreen extends StatefulWidget { const FlowScreen({super.key}); @override State<FlowScreen> createState() => _FlowScreenState(); } class _FlowScreenState extends State<FlowScreen> { @override void initState() { super.initState(); _showFlowIfNeeded(); } Future<void> _showFlowIfNeeded() async { try { final flow = await Adapty().getFlow( placementId: 'YOUR_PLACEMENT_ID', ); if (!flow.hasViewConfiguration) return; final view = await AdaptyUI().createFlowView(flow: flow); await view.present(); } catch (_) { // Handle any errors (network, SDK issues, etc.) } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Adapty Flow Example')), body: Center( // Add a button to re-trigger the flow for testing purposes. child: ElevatedButton( onPressed: _showFlowIfNeeded, child: const Text('Show Flow'), ), ), ); } } ``` --- # File: flutter-check-subscription-status --- --- title: "Flutter SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Flutter uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir. Bu makalede, kullanıcılara paywall mı göstermeniz gerektiğini yoksa ücretli özelliklere erişim mi tanımanız gerektiğini belirlemek için profil durumuna nasıl erişeceğinizi öğreneceksiniz. ## Abonelik durumunu alma \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profilindeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verilerine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) veya güncellemeyi zorlamak istediğinizde `getProfile` çağırın. - Abonelik durumu her değiştiğinde otomatik olarak güncellenen yerel bir kopya tutmak için **otomatik profil güncellemeleri** ayarlayın. ### Profil alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek üzere `Adapty().didUpdateProfileStream.listen()` kullanın — kullanıcının abonelik durumu her değiştiğinde Adapty bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncel profil verilerini saklayın; böylece ek ağ isteği yapmadan uygulama genelinde kullanabilirsiniz. ```dart class SubscriptionManager { AdaptyProfile? _currentProfile; SubscriptionManager() { // Listen for profile updates Adapty().didUpdateProfileStream.listen((profile) { _currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() bool hasAccess() { return _currentProfile?.accessLevels['premium']?.isActive ?? false; } } ``` :::note Adapty, uygulamanız başladığında profil güncelleme akışı dinleyicisini otomatik olarak çağırır ve cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sağlar. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim tanıma konusunda anlık kararlar almanız gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girerken veya belirli içerikleri görüntülemeden önce gibi senaryolar için kullanışlıdır. ```dart Future<bool> _checkAccessLevel() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false; } catch (e) { print('Error checking access level: $e'); return false; // Show paywall if access check fails } } Future<void> _initializePaywall() async { await _loadPaywall(); final hasAccess = await _checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların satın aldıklarına erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](flutter-quickstart-identify) öğrenin. --- # File: flutter-quickstart-identify --- --- title: "Flutter SDK'da kullanıcıları tanımlama" description: "Flutter'da uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa sizin içindir. Burada, Adapty'deki kullanıcı profilleriyle nasıl çalışacağınızı ve bunları mevcut kimlik doğrulama sisteminizle nasıl uyumlu hale getireceğinizi öğreneceksiniz. ::: Kullanıcıların satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız arka uç kimlik doğrulaması kullanmıyor ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanızda arka uç kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılar bölümüne](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmadan)** veya tanımlanmış **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi iç kimlik doğrulama sisteminizle çapraz referanslamak için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar şöyledir: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |-------------------------|------------------------------------------------------------|----------------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arasında satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profiller | Oturumlar ve cihazlar arasında aynı profil | | **Veri kalıcılığı** | Anonim kullanıcıların verileri uygulama kurulumuna bağlıdır | Tanımlanmış kullanıcıların verileri uygulama kurulumları arasında kalıcı olarak saklanır | ## Anonim kullanıcılar \{#anonymous-users\} Arka uç kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK, uygulamanın ilk başlatılmasında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profilleriyle ve mağaza hesaplarıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **etkinleştirmede yeni bir anonim profil oluşturur**. 4. Kullanıcı daha önce uygulamanızda satın alma yaptıysa, varsayılan olarak satın almaları SDK etkinleştirildiğinde App Store'dan otomatik olarak senkronize edilir. Anonim kullanıcılarla her kurulumda yeni profiller oluşturulur; ancak bu bir sorun değildir çünkü Adapty analitiğinde [neyin yeni kurulum sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için kurulumları **cihaz kimliklerine** göre saymanız gerekir. Bu durumda, bir cihazdaki her uygulama kurulumu (yeniden yüklemeler dahil) bir kurulum olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamadaki kullanıcıları tanımlamak için iki seçeneğiniz var: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğrulandıklarında customer user ID ile `identify()` çağrısı yapın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başlatıldığında zaten bir customer user ID saklıyorsanız, bunu `activate()` çağrısında gönderin. :::important Varsayılan olarak, Adapty başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; böylece her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Ayrıntılar için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kaydolduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty bunu otomatik olarak mevcut profille ilişkilendirir. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı kimlikleri her kullanıcı için benzersiz olmalıdır. Parametre değerini sabit kodlarsanız, tüm kullanıcılar tek bir kullanıcı olarak kabul edilir. ::: Diğer SDK metodlarını çağırmadan önce her zaman `identify` işlemini `await` ile bekleyin. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar veya anonim profile düşer. Bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Her kullanıcı için benzersiz } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### SDK etkinleştirmesi sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` metodunu ayrıca çağırmak yerine bunu `activate` metodunda gönderebilirsiniz. Bir customer user ID bilseniz de bunu yalnızca etkinleştirmeden sonra ayarlarsanız, etkinleştirme sırasında Adapty yeni bir anonim profil oluşturacak ve yalnızca `identify` çağrısından sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane geçirebilirsiniz. Yeni bir tane geçirirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID ile ilişkilendirilir. :::note Varsayılan olarak, anonim profil oluşturmak analitik kontrol panellerini etkilemez çünkü kurulumlar cihaz kimliklerine göre sayılır. Bir cihaz kimliği, bir cihazdaki mağazadan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, bunun birinci mi yoksa tekrarlanan bir kurulum mu olduğuna, ya da mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturma (SDK etkinleştirmesinde veya oturum kapatmada), giriş yapma veya uygulamayı yeniden yüklemeden yükseltme ek kurulum olayları oluşturmaz. Kurulumları benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** sayfasına gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) seçeneğini yapılandırın. ::: ```dart showLineNumbers" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. ); } catch (e) { // handle the error } ``` ### Kullanıcıları oturumu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir düğmeniz varsa, `logout` metodunu kullanın. :::important Kullanıcıların oturumunu kapatmak, kullanıcı için yeni bir anonim profil oluşturur. ::: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::info Kullanıcıları uygulamaya tekrar giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın alma yapılmasına izin verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıktan sonra erişimlerini korumalarını sağlamanız gerekir: 1. Oturum açmamış bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil kimliğiyle ilişkilendirir. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin, satın alma kayıt öncesinde yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profille bağlantılıysa), profil geçişinden sonra gerçek access level'ı almanız gerekir. Tanımlamanın hemen ardından [`getProfile`](flutter-check-subscription-status) çağrısı yapabilir veya veriler otomatik olarak senkronize olsun diye [profil güncellemelerini dinleyebilirsiniz](flutter-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını başarıyla uyguladınız! Uygulama gelir elde etme sürecinizde başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboardinglar**](flutter-onboardings): Onboardinglarla kullanıcıları etkileyin ve elde tutmayı artırın - [**Entegrasyonlar**](configuration): Pazarlama attribution ve analitik hizmetleriyle tek satır kodla entegre edin - [**Özel profil özellikleri ayarlama**](flutter-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywalllar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-flutter --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Flutter uygulamanıza entegre edin" description: "Adapty SDK'sını Flutter uygulamanıza baştan sona entegre etmek için AI kodlama aracınızla adapty-sdk-integration becerisini kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu beceri beta aşamasındadır. Takılıp kalır veya beklenmedik şekilde davranırsa, AI aracınıza her aşamayı doğru belgelerle adım adım anlatan [adım adım entegrasyon kılavuzunu](adapty-cursor-flutter) izleyin. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-flutter --- --- title: "Adapty'yi Flutter uygulamanıza yapay zeka yardımıyla entegre etme" description: "Cursor, Context7, ChatGPT, Claude veya diğer yapay zeka araçlarını kullanarak Adapty'yi Flutter uygulamanıza adım adım entegre etme rehberi." --- Bu rehber, bir yapay zeka kodlama aracıyla Adapty'yi Flutter uygulamanıza adım adım entegre etme sürecini anlatır — doğru Adapty dokümanlarını doğru sırada besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce biraz kontrol paneli yapılandırması gerektirir. Bunu etkileşimli bir LLM becerisini kullanarak ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilir) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywall'larınızı ve placement'larınızı doğrudan — her adım için Kontrol Paneli'ni açmadan — kurmasına olanak tanır. Yalnızca Kontrol Paneli'nde [mağazalarınızı bağlamanız](integrate-payments) gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra, ajanınızda `/adapty-cli` komutunu çalıştırın. Mağazalarınızı bağlamak için Kontrol Paneli'ni ne zaman açacağınız dahil her adımda sizi yönlendirecektir. ### Kontrol Paneli Yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, herhangi bir kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için arayamaz; bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Flutter uygulamanız her iki platformu da hedefliyorsa hem App Store hem de Google Play'i bağlayın. Bu, satın almaların çalışması için zorunludur. [Uygulama mağazalarını bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin ve **API keys** bölümünü bulun. Kodda bu, Adapty yapılandırmasına geçtiğiniz dizedir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere kodda doğrudan başvurmazsınız — Adapty onları paywall'lar aracılığıyla iletir. [Ürün ekleyin](quickstart-products) 4. **Paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasında bir paywall oluşturun, ardından **Placements** sayfasında bunu bir placement'a atayın. Kodda, placement ID, `Adapty().getPaywall()` fonksiyonuna geçirdiğiniz string değerdir. [Paywall oluştur](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde, **Products** sayfasında her ürün için yapılandırın. Kodda, `profile.accessLevels['premium']?.isActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne bağlı olarak farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Beş bilgiye de sahip olduğunuzda kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'im Y" — böylece doğru başlatma ve paywall çekme kodunu üretebilir. ::: ### Hazır olduğunuzda ayarlayın \{#set-up-when-ready\} Kodlamaya başlamak için bunlar zorunlu değildir, ancak entegrasyonunuz olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliğine gerek yoktur. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum, entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## LLM'nize Adapty Dokümanlarını Besleyin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi Kullanın (önerilir) [Context7](https://context7.com), LLM'inize güncel Adapty belgelerine doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, ne sorduğunuza göre doğru belgeleri otomatik olarak getirir — manuel URL yapıştırmaya gerek yok. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurulum için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, editörünüzü algılayarak Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırdıktan sonra, Adapty kütüphanesini prompt'larınızda referans alın: ``` Use the adaptyteam/adapty-docs library to look up how to install the Flutter SDK ``` :::warning Context7, belge bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalıştığından emin olmak için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanlara erişin \{#use-plain-text-docs\} Her Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** düğmesine tıklayın. Örneğin: [adapty-cursor-flutter.md](https://adapty.io/docs/tr/adapty-cursor-flutter.md). Aşağıdaki [uygulama adım adım rehberi](#implementation-walkthrough)'nin her aşaması, yapıştırabileceğiniz `.md` bağlantılarıyla birlikte "Bunu LLM'nize gönderin" bloğu içerir. Aynı anda daha fazla doküman için aşağıdaki [dizin dosyalarına ve platforma özgü alt kümelere](#plain-text-doc-index-files) bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, Adapty entegrasyonunu uygulama sırasına göre ele alır. Her aşamada LLM'inize göndereceğiniz belgeler, tamamlandığında ne görmeniz gerektiği ve sık karşılaşılan sorunlar açıklanmaktadır. ### Entegrasyonunuzu Planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inize projenizi analiz etmesini ve bir uygulama planı oluşturmasını söyleyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), bunu kullanın; böylece LLM herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilir. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, takip etmesi gereken kılavuzları etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin no-code editöründe paywall'lar oluşturursunuz; SDK bunları otomatik olarak render eder. - [**Manuel oluşturulan paywall'lar**](flutter-making-purchases): Kendi paywall arayüzünüzü kod ile oluşturursunuz, ancak ürünleri çekmek ve satın almaları yönetmek için yine Adapty'yi kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korursunuz ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Quickstart'taki karşılaştırma tablosuna](flutter-quickstart-paywalls) göz atın. ### SDK'yı Yükleyin ve Yapılandırın \{#install-and-configure-the-sdk\} `flutter pub add` komutunu kullanarak Adapty SDK bağımlılığını ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temel adımdır — geri kalan her şey buna bağlıdır. **Kılavuz:** [Adapty SDK'yı Yükleyin ve Yapılandırın](sdk-installation-flutter) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-flutter.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Uygulama hem iOS hem Android'de derlenir ve çalışır. Hata ayıklama konsolu Adapty aktivasyon logunu gösterir. - **Dikkat:** "Public API key is missing" → yer tutucuyu **App settings** bölümündeki gerçek anahtarınızla değiştirdiğinizi kontrol edin. ::: ### Paywall'ları göster ve satın almaları yönet \{#show-paywalls-and-handle-purchases\} Placement ID'ye göre bir paywall getir, görüntüle ve satın alma olaylarını yönet. İhtiyacınız olan kılavuzlar, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerledikçe sandbox'ta test et — sona kadar bekleme. Kurulum talimatları için [Sandbox'ta satın almaları test et](test-purchases-in-sandbox) bölümüne bakın. <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **Kılavuzlar:** - [Paywall'lar ile satın almaları etkinleştirme (hızlı başlangıç)](flutter-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını alma](flutter-get-pb-paywalls) - [Paywall'ları gösterme](flutter-present-paywalls) - [Paywall olaylarını işleme](flutter-handling-events) - [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) Bu, çevrilecek herhangi bir MDX dokümantasyon içeriği içermiyor — yalnızca bir LLM'e gönderilmesi amaçlanmış bir kod bloğu var. Çevrilecek bir MDX dosyası gönderirseniz memnuniyetle çeviririm. :::tip[Checkpoint] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu açar. - **Dikkat:** Boş paywall veya `getPaywall` hatası → placement ID'nin kontrol paneliyle tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manuel paywall'lar"> **Kılavuzlar:** - [Özel paywallınızda satın almaları etkinleştirin (hızlı başlangıç)](flutter-quickstart-manual) - [Paywallları ve ürünleri getirin](fetch-paywalls-and-products-flutter) - [Remote config ile tasarlanmış paywall'ı gösterin](present-remote-config-paywalls-flutter) - [Satın alma yapın](flutter-making-purchases) - [Satın almaları geri yükleyin](flutter-restore-purchase) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-flutter.md - https://adapty.io/docs/tr/present-remote-config-paywalls-flutter.md - https://adapty.io/docs/tr/flutter-making-purchases.md - https://adapty.io/docs/tr/flutter-restore-purchase.md ``` :::tip[Checkpoint] - **Beklenen:** Özel paywall'ınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma diyaloğunu tetikliyor. - **Sorun yaşıyorsanız:** Ürün dizisi boş → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitleye sahip olduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Observer mode"> **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode-flutter) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode-flutter) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-flutter.md - https://adapty.io/docs/tr/report-transactions-observer-mode-flutter.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak yapılan bir sandbox satın alımından sonra, işlem Adapty kontrol panelindeki **Event Feed** bölümünde görünür. - **Dikkat:** Hiç event yoksa → işlemleri Adapty'e raporladığınızı ve sunucu bildirimlerinin her iki mağaza için yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol etme \{#check-subscription-status\} Satın alımın ardından, premium içeriğe erişimi kısıtlamak için kullanıcı profilindeki aktif access level'ı kontrol edin. **Kılavuz:** [Abonelik durumunu kontrol etme](flutter-check-subscription-status) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın alımının ardından `profile.accessLevels['premium']?.isActive` değeri `true` döner. - **Dikkat:** Satın alımdan sonra `accessLevels` boş geliyor → ürüne kontrol panelinde bir access level atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Uygulama kullanıcı hesaplarını Adapty profillerine bağlayarak satın alımların cihazlar arasında kalıcı olmasını sağlayın. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](flutter-quickstart-identify) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/flutter-quickstart-identify.md ``` :::tip[Checkpoint] - **Beklenen:** `Adapty().identify()` çağrısından sonra, kontrol panelindeki **Profiles** bölümünde özel kullanıcı kimliğiniz görünür. - **Dikkat:** Anonim profil attribution sorunlarından kaçınmak için `identify` fonksiyonunu aktivasyondan sonra, paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlanma \{#prepare-for-release\} Entegrasyonunuz sandbox ortamında çalışır hale geldikten sonra, her şeyin production'a hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Rehber:** [Yayın kontrol listesi](release-checklist) Bunu LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Checkpoint] - **Beklenen:** Tüm kontrol listesi maddeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Sunucu bildirimleri eksikse → **App settings → iOS SDK** bölümünden App Store Server Notifications'ı ve **App settings → Android SDK** bölümünden Google Play Real-Time Developer Notifications'ı yapılandırın. ::: ## Düz metin belge indeks dosyaları \{#plain-text-doc-index-files\} LLM'nize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty belgelerini listeleyen veya bir araya getiren indeks dosyaları sunuyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı yapay zeka ajanlarının (örneğin ChatGPT) `llms.txt` dosyasını indirip sohbete yüklemeniz gerekebileceğini unutmayın. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hâlde. Çok büyük — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Flutter'a özel [`flutter-llms.txt`](https://adapty.io/docs/tr/flutter-llms.txt) ve [`flutter-llms-full.txt`](https://adapty.io/docs/tr/flutter-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: flutter-get-pb-paywalls --- --- title: "Flow'ları ve paywall'ları getir - Flutter" description: "Flutter uygulamanızda Adapty'den flow'ları ve paywall'ları çekin." --- <SDKv4> <MethodPromo method="getFlow" /> [Flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'ı ve görünüm yapılandırmasını almaktır. Bu konunun flow'lar ve Paywall Builder ile özelleştirilmiş paywalllar için geçerli olduğunu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywalllar için paywallları ve ürünleri getirme](fetch-paywalls-and-products-flutter) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow ve paywallları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-flutter)'yı yükleyin. </details> ## Flow/paywall getir \{#fetch-flowpaywall\} Flow Builder veya Paywall Builder ile bir flow veya paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir flow veya paywall, içinde neyin ve nasıl gösterileceğini zaten içerir. Yine de placement aracılığıyla ID'sini, görünüm konfigürasyonunu almanız ve ardından mobil uygulamanızda sunmanız gerekir. Flow veya paywall'ı mümkün olduğunca erken — ideally sunarken değil, çok daha önce — çekin ve [görünümünü](flutter-get-pb-paywalls#fetch-the-view-configuration) oluşturun. `createFlowView` metodu görünüm yapılandırmasını yükler ve arka planda görselleri indirip önbelleğe almaya başlar. Bu metodu ne kadar erken çağırırsanız, indirmelerin tamamlanması için o kadar fazla zaman olur. Flow veya paywall'ı sunduğunuzda, yapılandırma ve görseller zaten önbellekte hazır olabilir. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // istenen flow/paywall } on AdaptyError catch (adaptyError) { // hatayı işle } catch (e) { // hatayı işle } ``` Parametreler: | Parametre | Varlık | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye erişmesini sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirebilirsiniz. Bu senaryoda kullanıcılar en son veriye ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum süresince ağ isteklerini azaltmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlandığını unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda dahi güvenilirliği korurken her zaman paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu metodun zaman aşımını sınırlayan bir `Duration` değeri. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.</p> | ## Yanıt parametreleri \{#response-parameters\} | Parametre | Açıklama | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Flow'un tanımlayıcılarını (`instanceIdentity`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve remote config'leri (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## View konfigürasyonunu getirme \{#fetch-the-view-configuration\} :::important Builder'da **Show on device** geçiş düğmesini etkinleştirdiğinizden emin olun. Bu seçenek açık değilse, view konfigürasyonu getirilemez. ::: Eğer placement **Flow Builder** veya **Paywall Builder** ile tasarlandıysa, Adapty kullanıcı arayüzünü sizin için oluşturur — alınan flow'un `hasViewConfiguration` özelliği `true` olur. `createFlowView` ile görünümü oluşturun, ardından [flow veya paywall'ı gösterin](flutter-present-paywalls). Eğer placement, Builder arayüzü olmayan özel bir paywall ise (`hasViewConfiguration` değeri `false`), bunun yerine [remote config paywall olarak ele alın](present-remote-config-paywalls-flutter). :::warning `createFlowView` metodunun sonucu yalnızca bir kez sunulabilir. Tekrar sunmanız gerekiyorsa `createFlowView` metodunu yeniden çağırın. ::: ```dart showLineNumbers try { final view = await AdaptyUI().createFlowView(flow: flow); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | zorunlu | İstenen flow/paywall için bir görünüm elde etmek üzere kullanılan `AdaptyFlow` nesnesi. | | **customTags** | opsiyonel | Özel etiketlerin ve çözümlenmiş değerlerinin bir haritasını tanımlar. Özel etiketler içerikte yer tutucu işlevi görerek flow/paywall içindeki kişiselleştirilmiş içerik için belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için [Paywall Builder'da özel etiketler](custom-tags-in-paywall-builder) konusuna bakın. | | **preloadProducts** | opsiyonel | Ekranda ürünlerin gösterilme zamanlamasını optimize etmek için etkinleştirin. `true` olduğunda AdaptyUI gerekli ürünleri otomatik olarak getirir. Varsayılan: `false`. | | **loadTimeout** | opsiyonel | Görünüm yapılandırmasının yüklenme süresini sınırlayan bir `Duration`. Zaman aşımına ulaşıldığında önbelleğe alınmış veriler veya yerel yedek kullanılır. | :::note Birden fazla dil kullanıyorsanız, [flow yerelleştirmesi eklemeyi](add-paywall-locale-in-adapty-paywall-builder) ve yerel ayar kodlarını doğru kullanmayı [buradan](flutter-localizations-and-locale-codes) öğrenin. ::: Görünümü elde ettikten sonra, [flow/paywall'ı gösterin](flutter-present-paywalls). ## Varsayılan kitle için bir flow veya paywall alın, daha hızlı getirmek için \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'a sahip olduğunuz ve kullanıcılarınızın zayıf bir internet bağlantısı bulunduğu durumlarda, bir flow veya paywall getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklandığı üzere, `getFlow` metoduyla flow veya paywall getirmek olduğunu anlamak kritik önem taşır. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa, bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız gerekecek ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywall'larla karşılaşabileceğini kabul etmek durumunda kalacaksınız. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre) kaybetmeniz anlamına gelir. Bu dezavantajları kabul etmeye hazırsanız ve daha hızlı flow veya paywall yüklemenin avantajlarından yararlanmak istiyorsanız, `getFlowForDefaultAudience` yöntemini aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` yöntemini kullanmaya devam edin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow/paywall } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Bu seçeneği öneriyoruz çünkü kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar her zaman en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak amacıyla oturum boyunca kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p> | ## Öğeleri özelleştir \{#customize-assets\} Flow/paywall'ınızdaki görsel ve videoları özelleştirmek için özel öğeleri uygulayın. Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir öğe paketinde, bu öğeleri ID'leri üzerinden hedefleyerek davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterme. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterme. - Video başlamadan önce bir önizleme görseli gösterme. Here's an example of how you can provide custom assets via a simple dictionary: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createFlowView( flow: flow, customAssets: customAssets, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir varlık bulunamazsa, flow/paywall varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `createFlowView` metoduna bir `customTimers` map'i geçirin. Her map anahtarı bir zamanlayıcı ID'si, değeri ise zamanlayıcının ne zaman sona ereceğini tanımlayan bir `DateTime` nesnesidir. İşte bir örnek: ```dart showLineNumbers try { final view = await AdaptyUI().createFlowView( flow: flow, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2027, 1, 1), // New Year 2027 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `customTimers` haritası, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Zamanlayıcının bitiş zamanına (örneğin Yılbaşı Günü) kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının flow'u açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman. </SDKv4> <SDKv3> [Adapty Kontrol Paneli'nde yeni Paywall Builder ile paywall'ınızın görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda görüntüleyebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywall'ı ve görünüm yapılandırmasını almaktır. :::warning Yeni Paywall Builder, Flutter SDK 3.3.0 veya daha yüksek sürümlerle çalışır. ::: Lütfen bu konunun Paywall Builder ile özelleştirilmiş paywall'lara atıfta bulunduğunu unutmayın. Paywall'larınızı manuel olarak uyguluyorsanız, [Mobil uygulamanızda remote config paywall'ları için paywall ve ürünleri getirin](fetch-paywalls-and-products-flutter) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall'ları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-flutter)'yı kurun. </details> ## Paywall Builder ile tasarlanan paywall'ı getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yok. Bu tür bir paywall, paywall içinde ne gösterileceğini ve nasıl gösterileceğini içerir. Bununla birlikte, placement aracılığıyla kimliğini, görünüm konfigürasyonunu almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, paywall'ı ve [görünüm konfigürasyonunu](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız kritik önem taşır; böylece görseller kullanıcıya sunulmadan önce indirmek için yeterli süre kalır. Bir paywall almak için `getPaywall` metodunu kullanın: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametrenin eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) bölümüne bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak, kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda, kullanıcılar en son veriyi alamayabilir; ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Paywall'ları daha hızlı getirmek için CDN kullanıyoruz ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının kısıtlı olduğu durumlarda bile güvenilirliği sağlarken paywall'larınızın her zaman en son sürümünü almanızı sağlamak için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, bu metot için zaman aşımını sınırlar. Zaman aşımına ulaşılırsa, önbellekteki veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p><p>Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`, burada `.seconds`, `import com.adapty.utils.seconds`'dan gelir) veya `TimeInterval.seconds(5)` kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün kimliklerinin listesini, paywall tanımlayıcısını, remote config'i ve birçok diğer özelliği içeren bir [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | ## Paywall Builder ile tasarlanan paywall'ın görünüm konfigürasyonunu getirme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm konfigürasyonu alınamaz. ::: Paywall'ı aldıktan sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywall'ın nasıl gösterileceği konusunda size rehberlik edecektir. `ViewConfiguration` mevcutsa, bunu bir Paywall Builder paywall'ı olarak değerlendirin; değilse, [remote config paywall olarak ele alın](present-remote-config-paywalls-flutter). ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Görünümü aldıktan sonra [paywall'ı sunun](flutter-present-paywalls). ## Daha hızlı getirmek için varsayılan kitle paywall'ını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle paywall'lar neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywall'ınız varsa ve kullanıcılarınızın zayıf bir internet bağlantısı varsa, bir paywall'ı getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall göstermek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için paywall'ı getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Paywall Bilgisini Getirme](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklandığı gibi `getPaywall` metoduyla paywall'ı getirmek olduğunu anlamak çok önemlidir. :::warning `getPaywall` kullanmanızı neden öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız gerekecek ya da mevcut (eski) sürüme sahip kullanıcıların render edilmeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedeflemenin kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecek; bu, kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, aşağıdaki şekilde `getPaywallForDefaultAudience` metodunu kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall`'a bağlı kalın. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` metodu Flutter SDK 3.2.0 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametrenin eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) bölümüne bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak, kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda, kullanıcılar en son veriyi alamayabilir; ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Paywall'ınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videolar önceden tanımlanmış kimliklere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri kimliklerine göre hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir kimlik ayarlamanız](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Bir video çalıştırmadan önce önizleme görseli gösterin. :::important Bu özelliği kullanmak için Adapty Flutter SDK'yı 3.8.0 veya daha yüksek bir sürüme güncelleyin. ::: İşte basit bir sözlük aracılığıyla özel varlıkları nasıl sağlayabileceğinize dair bir örnek: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets: customAssets, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir varlık bulunamazsa, paywall varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `createPaywallView` metoduna bir `customTimers` haritası geçirin. Haritadaki her anahtar bir zamanlayıcı ID'sidir ve değeri zamanlayıcının ne zaman sona ereceğini tanımlayan bir `DateTime` nesnesidir. İşte bir örnek: ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2025, 1, 1), // New Year 2025 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `customTimers` haritası, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Yeni Yıl Günü gibi zamanlayıcının bitiş anına kadar kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının paywall'ı açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman. </SDKv3> --- # File: flutter-present-paywalls --- --- title: "Flow ve paywallları görüntüleme - Flutter" description: "Adapty'nin monetizasyon özelliklerini kullanarak Flutter uygulamalarında flow ve paywallları gösterin." --- <SDKv4> Flow Builder veya Paywall Builder kullanarak bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir flow veya paywall, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz, flow'lar ve Paywall Builder paywall'ları içindir. **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanmış paywall'ı render etme](present-remote-config-paywalls-flutter). ::: Adapty Flutter SDK, flow'ları ve paywall'ları sunmak için iki yol sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak göster \{#present-as-standalone-screen\} Bir flow veya paywall'ı bağımsız bir ekran olarak göstermek için, [`createFlowView`](flutter-get-pb-paywalls#fetch-the-view-configuration) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez gösterilebilir: kapatıldıktan sonra `view` bellekten serbest bırakılır. Flow veya paywall'ı tekrar göstermeniz gerekirse, yeni bir `view` örneği oluşturmak için `createFlowView` metodunu bir kez daha çağırın. ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Flow veya paywall'ı kapat \{#dismiss-the-flow-or-paywall\} Flow veya paywall'ı programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note Bir view kapatıldığında bellekten silinir — kapatılmış bir view artık yeniden gösterilemez. Bunun yerine `createFlowView` ile yeni bir tane oluşturun. ::: ### Diyalog göster \{#show-dialog\} Android'de bir flow veya paywall görünümü gösterildiğinde, native uyarı diyalogları yerine bu metodu kullanın. Android'de normal uyarılar görünümün arkasında kalır ve kullanıcılar tarafından görülemez. Bu metod, diyaloğun tüm platformlarda flow veya paywall'ın üzerinde düzgün şekilde gösterilmesini sağlar. ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek flow veya paywall'ın iOS'ta nasıl sunulacağını yapılandırın. Bu parametre `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine gömme \{#embed-in-widget-hierarchy\} Mevcut widget ağacınıza bir flow veya paywall gömmek için `AdaptyUIFlowPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIFlowPlatformView( flow: flow, // The flow object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidReceiveError: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android platform view'ın çalışması için `MainActivity`'nizin `FlutterFragmentActivity`'yi genişlettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: </SDKv4> <SDKv3> Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz yalnızca SDK v3.2.0 veya sonrasını gerektiren **yeni Paywall Builder paywall'ları** içindir. Paywall'ları sunma süreci, farklı Paywall Builder sürümleriyle tasarlanan paywall'lar ve remote config paywall'lar için farklılık gösterir. - **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls-flutter). ::: Adapty Flutter SDK, paywall'ları sunmak için iki yöntem sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak sunma \{#present-as-standalone-screen\} Bir paywall'ı bağımsız ekran olarak görüntülemek için, [`createPaywallView`](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar göstermeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createPaywallView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Paywall'ı kapatma \{#dismiss-the-paywall\} Paywall'ı programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Diyalog gösterme \{#show-dialog\} Android'de bir paywall görünümü sunulduğunda, yerel uyarı diyalogları yerine bu metodu kullanın. Android'de normal uyarılar paywall görünümünün arkasında kalır ve kullanıcılar tarafından görülemez. Bu metod, tüm platformlarda diyaloğun paywall'ın üzerinde düzgün şekilde gösterilmesini sağlar. ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek paywallın iOS'ta nasıl sunulacağını yapılandırın. Parametre, `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine gömme \{#embed-in-widget-hierarchy\} Bir paywall'ı mevcut widget ağacınıza gömmek için `AdaptyUIPaywallPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIPaywallPlatformView( paywall: paywall, // The paywall object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidFailRendering: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android platform view'un çalışması için `MainActivity` sınıfınızın `FlutterFragmentActivity`'yi extend ettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: </SDKv3> --- # File: flutter-handle-paywall-actions --- --- title: "Flutter SDK'da buton eylemlerine yanıt verme" description: "Adapty kullanarak Flutter'da paywall buton eylemlerini daha iyi uygulama monetizasyonu için yönetin." --- <SDKv4> Adapty builder kullanarak flow veya paywall oluşturuyorsanız, butonları doğru şekilde ayarlamak çok önemlidir: 1. [Builder'da bir buton ekleyin](paywall-buttons) ve ona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Uygulamanızda atadığınız her eylemi işlemek için kod yazın. Bu kılavuz, kodunuzda özel ve mevcut eylemlerin nasıl işleneceğini göstermektedir. :::warning **Görünümü kapatma ve URL'leri açma işlemleri**, varsayılan `flowViewDidPerformAction` uygulaması tarafından **otomatik olarak gerçekleştirilir** ve SDK'nın kendisi satın alma ile geri yükleme işlemlerini yönetir. Giriş yapma veya başka bir flow açma gibi diğer tüm buton eylemleri, uygulama kodunda uygun yanıtların yazılmasını gerektirir. *Tamamlanan* satın alma ve geri yükleme işlemlerine yanıt verme ise zorunlu gözlemci callback'lerinde gerçekleşir — bkz. [Flow & paywall olaylarını yönetme](flutter-handling-events). ::: ## Flow ve paywallları kapatma \{#close-flows-and-paywalls\} Flow veya paywallınıza kapatma düğmesi eklemek için builder'da bir düğme ekleyin ve bu düğmeye **Close** aksiyonunu atayın. Herhangi bir kod yazmanıza gerek yok: varsayılan `flowViewDidPerformAction` implementasyonu, `CloseAction` aldığında görünümü otomatik olarak kapatır. :::info Android sistem **Back** düğmesi artık görünümü varsayılan olarak kapatmıyor. Bu düğme, `flowViewDidPerformAction`'a `AndroidSystemBackAction` olarak iletilir; back düğmesinin flow veya paywallı kapatmasını istiyorsanız bunu kendiniz ele almanız gerekir. ::: Özel bir davranışa ihtiyaç duyuyorsanız `flowViewDidPerformAction` metodunu override edin — örneğin, v3'te olduğu gibi Android sistem geri tuşunda da görünümü kapatmak için: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(:final url, :final openIn): AdaptyUI().openUrl(url, openIn: openIn); break; default: break; } } ``` :::warning `flowViewDidPerformAction` metodunu override etmek, varsayılan implementasyonun tamamının yerini alır — varsayılan kapatma ve URL açma davranışını korumak istiyorsanız `CloseAction` ve `OpenUrlAction` case'lerini eklemeyi unutmayın. ::: ## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (ör. kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde yönetin. ::: Bir bağlantı açan düğme eklemek için (ör. **Terms of use** veya **Privacy policy**), builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. Varsayılan `flowViewDidPerformAction` implementasyonu URL'yi `AdaptyUI().openUrl` aracılığıyla yerel olarak açar; kontrol panelindeki uygulama içi veya harici tarayıcı ayarını dikkate alır. Bu nedenle herhangi bir kod yazmanız gerekmez. Varsayılan davranış çoğu durum için yeterlidir. URL'leri kendiniz açmak istiyorsanız handler'ı geçersiz kılın: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL in whatever way fits your app break; default: break; } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Builder'da bir buton ekleyin ve **Login** aksiyonunu atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` aksiyonu için bir işleyici uygulayın. ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Navigate to your login screen in whatever way fits your app break; default: break; } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yöneten bir buton eklemek için: 1. Builder'da bir buton ekleyin, **Custom** eylemini atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifleri veya tek seferlik satın alma seçenekleri setiniz varsa, başka bir flow veya paywall görüntüleyecek bir buton ekleyebilirsiniz: ```dart void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Display another flow or paywall break; default: break; } } ``` </SDKv4> <SDKv3> Adapty paywall builder kullanarak paywall oluşturuyorsanız, butonları doğru şekilde ayarlamak çok önemlidir: 1. [Paywall builder'a bir buton ekleyin](paywall-buttons) ve bu butona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Uygulamanızda, atadığınız her eylemi işleyecek kodu yazın. Bu rehber, kodunuzda özel ve mevcut aksiyonları nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar ve yenilemeler otomatik olarak işlenir.** Paywall'ları kapatma veya bağlantı açma gibi diğer tüm buton aksiyonları, uygulama kodunda uygun yanıtların uygulanmasını gerektirir. ::: ## Paywall'ları kapatma \{#close-paywalls\} Paywall'ınızı kapatacak bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda `CloseAction` ve `AndroidSystemBackAction` eylemleri için bir handler uygulayın. :::info Flutter SDK'da `CloseAction` ve `AndroidSystemBackAction` eylemleri varsayılan olarak paywall'ı kapatır. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywall'ı kapatmak başka bir paywall'ın açılmasını tetikleyebilir. ::: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; default: break; } } ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup link eklemek istiyorsanız (ör. kullanım koşulları ve satın alma restorasyon), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemine sahip butonlarla aynı şekilde yönetin. ::: Paywall'ınızdan link açan bir buton eklemek için (ör. **Kullanım Koşulları** veya **Gizlilik Politikası**): 1. Paywall builder'da bir buton ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi bir tarayıcıda açan `openUrl` eylemi için bir handler uygulayın. ```dart // You have to install url_launcher plugin in order to handle urls: // https://pub.dev/packages/url_launcher void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case OpenUrlAction(url: final url): final Uri uri = Uri.parse(url); launchUrl(uri, mode: LaunchMode.inAppBrowserView); break; default: break; } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcıyı tanımlayan `login` eylemi için bir işleyici uygulayın. ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Navigate to your login screen in whatever way fits your app break; default: break; } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer eylemleri yönetecek bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin, **Custom** eylemini atayın ve bir ID belirleyin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir handler uygulayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa, başka bir paywall görüntüleyen bir buton ekleyebilirsiniz: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Başka bir paywall göster break; default: break; } } ``` </SDKv3> --- # File: flutter-handling-events --- --- title: "Flutter - Flow ve paywall etkinliklerini yönetme" description: "Kullanıcı etkileşimlerini etkin şekilde izlemek için Adapty ile Flutter'da abonelikle ilgili olayları nasıl yöneteceğinizi keşfedin." --- <SDKv4> :::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve render etme olaylarını kapsar. Görünümü kapatma ve bağlantı açma işlemleri, varsayılan `flowViewDidPerformAction` uygulaması tarafından yönetilir — bunları geçersiz kılmak veya özel buton eylemlerini işlemek için [buton eylemlerini yönetme kılavuzumuza](flutter-handle-paywall-actions) bakın. ::: Flow ve Paywall Builder ile oluşturulan paywall'lar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamaları (kapatma düğmeleri, URL'ler, ürün seçimleri vb.) ve flow veya paywall üzerinde gerçekleştirilen satın alma işlemlerine ilişkin bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızdaki flow veya paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIFlowsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setFlowsEventsObserver(this); ``` Üç observer metodu **zorunludur** — sınıfınız bunlar olmadan derlenmez: `flowViewDidFinishPurchase`, `flowViewDidFinishRestore` ve `flowViewDidReceiveError`. Diğer tüm metodlar isteğe bağlıdır. Daha önce ayarlanmış bir observer'ı kaldırmak için `setFlowsEventsObserver`'a `null` geçin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: Aşağıdaki olay örnekleri, her nesne üzerinde mevcut olan özellikleri ve yorumlarda örnek değerleri göstermektedir. ### Kullanıcı tarafından oluşturulan olaylar \{#user-generated-events\} #### Görünüm belirdi \{#view-appeared\} Bu metot, flow veya paywall görünümü ekranda gösterildiğinde çağrılır. :::note iOS'ta, kullanıcı bir paywall içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve bir web paywall uygulama içi tarayıcıda açıldığında da çağrılır. ::: ```dart showLineNumbers title="Flutter" void flowViewDidAppear(AdaptyUIFlowView view) { } ``` #### Görünüm kayboldu \{#view-disappeared\} Bu metot, flow veya paywall görünümü ekrandan kaldırıldığında çağrılır. :::note iOS'ta ayrıca, bir paywall'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button)'ı uygulama içi tarayıcıda kapandığında da tetiklenir. ::: ```dart showLineNumbers title="Flutter" void flowViewDidDisappear(AdaptyUIFlowView view) { } ``` #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı ya da sistem tarafından), bu metot çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void flowViewDidSelectProduct(AdaptyUIFlowView view, String productId) { // productId is a String: productId; // 'premium_monthly' } ``` </Details> #### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) { } ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```dart void flowViewDidStartPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' product.localizedTitle; // 'Premium Monthly' product.localizedDescription; // 'Premium subscription for 1 month' product.price.amount; // 9.99 (double) product.price.currencyCode; // 'USD' product.price.localizedString; // '$9.99' } ``` </Details> #### Tamamlanan satın alma \{#finished-purchase\} Bu yöntem **zorunludur**. Bir satın alma başarıyla tamamlandığında, kullanıcı satın almayı iptal ettiğinde veya satın alma işlemi beklemede göründüğünde çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```dart void flowViewDidFinishPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) break; case AdaptyPurchaseResultPending(): // no additional data break; case AdaptyPurchaseResultUserCancelled(): // no additional data break; } } ``` </Details> :::info v3'ten farklı olarak, bu metodun varsayılan bir davranışı yoktur — başarılı bir satın alma sonrasında görünüm artık otomatik olarak kapatılmaz. Bundan sonra ne olacağına siz karar verin: flow'a devam edin veya `view.dismiss()` çağrısı yapın. Bir ekranı kapatma hakkında ayrıntılar için [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) bölümüne bakın. ::: #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Bu metod, belirli bir ürün için bir [web paywall](web-paywall) açma girişiminin ardından çağrılır. Hem başarılı hem de başarısız navigasyon girişimleri dahildir: ```dart showLineNumbers title="Flutter" void flowViewDidFinishWebPaymentNavigation(AdaptyUIFlowView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **Parametreler:** | Parametre | Açıklama | |:------------|:------------------------------------------------------------------------------------------------------| | **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir. | | **error** | Web paywall navigasyonu başarısız olduysa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. | #### Başarısız satın alma \{#failed-purchase\} Bu yöntem, bir satın alma başarısız olduğunda (örneğin, ödeme sorunları veya ağ hataları nedeniyle) çağrılır. Kullanıcının başlattığı iptaller veya bekleyen işlemler için **tetiklenmez** — bunlar `flowViewDidFinishPurchase` tarafından ele alınır: ```dart showLineNumbers title="Flutter" void flowViewDidFailPurchase(AdaptyUIFlowView view, AdaptyPaywallProduct product, AdaptyError error) { } ``` #### Geri yükleme başlatıldı \{#started-restore\} Bir kullanıcı geri yükleme işlemini başlatırsa bu yöntem çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidStartRestore(AdaptyUIFlowView view) { } ``` #### Başarılı geri yükleme \{#successful-restore\} Bu metod **zorunludur**. Bir satın alma geri yükleme işlemi başarılı olursa çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { } ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```dart void flowViewDidFinishRestore(AdaptyUIFlowView view, AdaptyProfile profile) { // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) profile.subscriptions['premium_monthly']?.isActive; // true profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) } ``` </Details> Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](flutter-listen-subscription-changes) konusuna, ekranı nasıl kapatacağınızı öğrenmek için ise [Buton eylemlerine yanıt verme](flutter-handle-paywall-actions) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} Bir satın alma geri yüklemesi başarısız olursa şu metod çağrılır: ```dart showLineNumbers title="Flutter" void flowViewDidFailRestore(AdaptyUIFlowView view, AdaptyError error) { } ``` ### Veri çekme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürün dizisini geçmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir: ```dart showLineNumbers title="Flutter" void flowViewDidFailLoadingProducts(AdaptyUIFlowView view, AdaptyError error) { } ``` #### Görünüm hataları \{#view-errors\} Bu yöntem **zorunludur**. v3'teki `paywallViewDidFailRendering` yönteminin yerini alır: arayüz oluşturma sırasında meydana gelen hatalar ve diğer görünüm hataları bu yöntem çağrılarak raporlanır. Bir kez uyguladığınızda, kapatma işlemi size kalmıştır — bu tür hatalarda görünümü kapatmanızı öneririz; hiçbir gözlemci ayarlanmadığında SDK'nın yerleşik varsayılanı da bunu yapar: ```dart showLineNumbers title="Flutter" void flowViewDidReceiveError(AdaptyUIFlowView view, AdaptyError error) { // log the error and dismiss the broken view view.dismiss(); } ``` Normal bir durumda render hataları oluşmamalıdır; eğer biriyle karşılaşırsanız lütfen bize bildirin. ### Analitik olayları \{#analytics-events\} İsteğe bağlı `flowViewDidReceiveAnalyticEvent` metodu, bir flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmediğinden, bu metodu uygulamanıza gerek yoktur. ### Observer mode'da satın almaları yönetme \{#handle-purchases-in-observer-mode\} SDK'yı [Observer mode](implement-observer-mode-flutter)'da etkinleştirdiyseniz ve Adapty tarafından oluşturulan bir flow veya paywall sunuyorsanız, SDK satın alma işlemlerini sizin adınıza gerçekleştirmez. Kullanıcı satın alma veya geri yükleme düğmesine dokunduğunda SDK, `AdaptyUIObserverModeResolver`'ınızı çağırır. Tam kurulum için bkz. [Observer mode'da flow sunma](flutter-present-flows-in-observer-mode). ### Sistem isteklerini yönetme \{#handle-system-requests\} `AdaptyUISystemRequestsHandler` (`AdaptyUI().setSystemRequestsHandler(...)` aracılığıyla kaydedilir), bir flow'dan gelen sistem istekleri için ayrılmıştır: işletim sistemi izin istemleri (push bildirimleri veya kamera erişimi gibi) ve App Store inceleme istekleri. Flow'lar henüz bu istekleri tetiklemiyor, dolayısıyla bir handler kaydetmeniz gerekmiyor. Eğer birini kayıt ederseniz, `handlePermission`'ın sınıfın zorunlu metodu olduğunu unutmayın — izni kendi kodunuzla isteyin, ardından `AdaptyUIPermissionResult.granted()` veya `AdaptyUIPermissionResult.denied()` döndürün; `handleAppReviewRequest` ise isteğe bağlıdır. </SDKv4> <SDKv3> :::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve paywall render işlemlerine ait olay yönetimini ele almaktadır. Bunların yanı sıra düğme yönetimini de (paywall'ı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [düğme eylemlerini yönetme kılavuzumuza](flutter-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış paywalllar, satın alma ve geri yükleme işlemleri için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamalarını (kapatma butonları, URL'ler, ürün seçimleri vb.) ve paywall'da gerçekleştirilen satın alma ile ilgili eylemlerin bildirimlerini içerir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. :::warning Bu kılavuz yalnızca Adapty SDK v3.0 veya üzerini gerektiren **yeni Paywall Builder paywallları** içindir. ::: Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIPaywallsEventsObserver` metodlarını uygulayın ve herhangi bir ekran gösterilmeden önce observer'ı ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setPaywallsEventsObserver(this); ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: Aşağıdaki olay örnekleri, her nesnede bulunan özellikleri ve yorumlarda açıklayıcı değerleri göstermektedir. ### Kullanıcı tarafından tetiklenen olaylar #### Paywall göründü \{#paywall-appeared\} Bu yöntem, paywall görünümü ekranda gösterildiğinde çağrılır. :::note iOS'ta, ayrıca kullanıcı bir paywall içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve web paywall uygulama içi tarayıcıda açıldığında da çağrılır. ::: ```dart showLineNumbers title="Flutter" void paywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### Paywall kayboldu \{#paywall-disappeared\} Bu yöntem, paywall görünümü ekrandan kaldırıldığında çağrılır. :::note iOS'ta, bir paywall'dan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button)'ın uygulama içi tarayıcıdan ekrandan kaybolması durumunda da çağrılır. ::: ```dart showLineNumbers title="Flutter" void paywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### Ürün seçimi \{#product-selection\} Bir ürün satın alma için seçildiğinde (kullanıcı veya sistem tarafından), bu metod çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { // productId is a String: productId; // 'premium_monthly' } ``` </Details> #### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma işlemini başlatırsa bu metod çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' product.localizedTitle; // 'Premium Monthly' product.localizedDescription; // 'Premium subscription for 1 month' product.price.amount; // 9.99 (double) product.price.currencyCode; // 'USD' product.price.localizedString; // '$9.99' } ``` </Details> #### Tamamlanan satın alma \{#finished-purchase\} Bu metot, bir satın alma işlemi başarıyla tamamlandığında, kullanıcı satın alma işlemini iptal ettiğinde veya satın alma işlemi beklemede göründüğünde çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) break; case AdaptyPurchaseResultPending(): // no additional data break; case AdaptyPurchaseResultUserCancelled(): // no additional data break; } } ``` </Details> Bu durumda ekranı kapatmanızı öneririz. Bir paywall ekranını kapatma hakkında ayrıntılı bilgi için [Düğme eylemlerine yanıt verme](flutter-handle-paywall-actions) bölümüne bakın. #### Web ödeme gezintisi tamamlandı \{#finished-web-payment-navigation\} Bu metot, belirli bir ürün için [web paywall](web-paywall) açma girişiminin ardından çağrılır. Başarılı ve başarısız gezinti girişimlerinin her ikisini de kapsar: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **Parametreler:** | Parametre | Açıklama | |:------------|:----------------------------------------------------------------------------------------------------------------| | **product** | Web paywallın açıldığı `AdaptyPaywallProduct`. `null` olabilir. | | **error** | Web paywall navigasyonu başarısız olduysa `AdaptyError` nesnesi; navigasyon başarılıysa `null`. | <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { // product — AdaptyPaywallProduct?: product?.vendorProductId; // 'premium_monthly' if (error == null) { // navigation succeeded } else { // error — AdaptyError: error.code; // AdaptyErrorCode.networkFailed (2005) error.message; // 'Network request failed' error.detail; // platform-specific underlying error, or null } } ``` </Details> #### Başarısız satın alma \{#failed-purchase\} Bu yöntem, bir satın alma işlemi başarısız olduğunda (örneğin, ödeme sorunları veya ağ hataları nedeniyle) çağrılır. Kullanıcının iptal ettiği veya beklemedeki işlemler için **tetiklenmez**; bunlar `paywallViewDidFinishPurchase` tarafından işlenir: ```dart showLineNumbers title="Flutter" void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { // product — AdaptyPaywallProduct: product.vendorProductId; // 'premium_monthly' // error — AdaptyError: error.code; // AdaptyErrorCode.productPurchaseFailed (1006) error.message; // 'Product purchase failed.' error.detail; // platform-specific underlying error, or null } ``` </Details> #### Geri yükleme başlatıldı \{#started-restore\} Bir kullanıcı geri yükleme işlemini başlatırsa bu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### Başarılı geri yükleme \{#successful-restore\} Bir satın alma başarıyla geri yüklenirse şu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { // profile — AdaptyProfile: profile.accessLevels['premium']?.isActive; // true profile.accessLevels['premium']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) profile.subscriptions['premium_monthly']?.isActive; // true profile.subscriptions['premium_monthly']?.expiresAt; // DateTime(2027, 2, 15, 10, 30) } ``` </Details> Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](flutter-listen-subscription-changes) konusuna, paywall ekranını nasıl kapatacağınızı öğrenmek için [Düğme eylemlerine yanıt verme](flutter-handle-paywall-actions) konusuna bakın. #### Geri yükleme başarısız oldu \{#failed-restore\} Bir satın alma geri yüklemesi başarısız olursa bu metot çağrılır: ```dart showLineNumbers title="Flutter" void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.receiveRestoredTransactionsFailed (1011) error.message; // 'Error occurred in the process of restoring purchases.' error.detail; // platform-specific underlying error, or null } ``` </Details> ### Veri getirme ve render etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürün dizisini geçmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa AdaptyUI, hatayı şu metodu çağırarak bildirir: ```dart showLineNumbers title="Flutter" void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.productRequestFailed (1002) error.message; // 'Unable to fetch available In-App Purchase products at the moment.' error.detail; // platform-specific underlying error, or null } ``` </Details> #### Render hataları \{#rendering-errors\} Arayüz oluşturma sırasında bir hata oluşursa, bu metot çağrılarak hata bildirilir. Varsayılan olarak (v3.15.2'den itibaren), oluşturma hatası meydana geldiğinde paywall otomatik olarak kapatılır; ancak gerekirse bu davranışı değiştirebilirsiniz. ```dart showLineNumbers title="Flutter" void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // Default behavior: view.dismiss() // Override with custom logic if needed, for example: // - Log the error // - Show an error message to the user } ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```dart void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // error — AdaptyError: error.code; // AdaptyErrorCode.jsException (4105) error.message; // 'An exception was thrown from JS during AdaptyUI flow execution.' error.detail; // platform-specific underlying error, or null // Default behavior: view.dismiss() } ``` </Details> Normal şartlarda böyle hatalarla karşılaşılmamalıdır; eğer bununla karşılaşırsanız lütfen bize bildirin. </SDKv3> --- # File: flutter-use-fallback-paywalls --- --- title: "Flutter - Yedek paywall kullanımı" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucularına ulaşılamadığında ne yapılacağını öğrenin" --- :::warning Yedek paywalllar Flutter SDK v2.11 ve sonrası tarafından desteklenmektedir. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek yapılandırma dosyalarını projenin kök dizinindeki `assets` klasörüne ekleyin. 2. Hedef paywall veya onboarding'i almadan **önce** `.setFallback` metodunu çağırın. ```dart showLineNumbers title="Flutter" final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { await Adapty().setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parametreler: | Parametre | Açıklama | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **assetId** | Yedek yapılandırma dosyasının yolu. | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: flutter-localizations-and-locale-codes --- --- title: "Flutter SDK'da yerelleştirmeleri ve yerel ayar kodlarını kullanma" description: "Global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin." --- <SDKv4> ## Bu neden önemli \{#why-this-is-important\} Adapty bir flow için yerelleştirme seçerken ve özel paywall için remote config okurken locale kodları devreye girer. Locale kodları karmaşık bir yapıya sahiptir ve platformdan platforma farklılık gösterebilir; bu nedenle Adapty desteklediği her platformda tek bir iç standarda dayanır. Bu standardı anlamak, bir kullanıcının hangi yerelleştirmeyi alacağını önceden tahmin etmenizi sağlar. ## Adapty'de dil kodu standardı \{#locale-code-standard-at-adapty\} Dil kodları için Adapty, [BCP 47 standardının](https://en.wikipedia.org/wiki/IETF_language_tag) hafifçe değiştirilmiş bir versiyonunu kullanır: her kod, tire ile ayrılmış küçük harf alt etiketlerinden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, kullanıcının yerel ayarıyla eşleşen lokalizasyonu ararken şu adımları izler: 1. Yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgiyle (`-`) değiştirilir 2. Adapty, tam olarak eşleşen yerel ayar koduyla lokalizasyonu arar 3. Eşleşme bulunamazsa, Adapty ilk kısa çizgiden önceki alt dizeyi alır (`pt-br` için `pt`) ve eşleşen lokalizasyonu arar 4. Yine eşleşme bulunamazsa, Adapty varsayılan `en` lokalizasyonunu döndürür Bu şekilde `'pt_BR'`, `pt-BR` ve `pt-br` hepsi aynı lokalizasyona karşılık gelir. ## Yerelleştirmeleri Uygulamak \{#implementing-localizations\} SDK v4'te bir flow çekerken locale kodu iletmezsiniz. - **Flow Builder ve Paywall Builder paywalls'ları**: Adapty, yerelleştirmeyi cihazdan ve builder'da yapılandırdığınız yerelleştirmelerden otomatik olarak çözer. Flow'u `createFlowView` ile render edin — locale koduna gerek yok. - **Özel (remote config) paywalls'lar**: `getFlow`, yapılandırılmış tüm yerelleştirmeleri `flow.remoteConfigs` içinde döndürür. Her girdinin bir `locale` kodu ve config içeriği (`data` dizesi veya ayrıştırılmış `dictionary`) bulunur. Kullanıcıya uyan girdiyi kendi yedek mantığınızla seçin: ```dart showLineNumbers final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final config = flow.remoteConfigs.firstWhereOrNull((c) => c.locale == 'en') ?? flow.remoteConfig; // the first remote config, if present // read your values from config?.dictionary ``` Yukarıdaki yerel ayar kodu eşleştirme kuralları, Adapty'nin her remote config üzerinde depolanan `locale` kodlarını nasıl normalleştirdiğini açıklar. </SDKv4> <SDKv3> ## Bu neden önemli \{#why-this-is-important\} Locale kodlarının devreye girdiği birkaç senaryo vardır; örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywall'ı çekmeye çalışırken. Locale kodları karmaşık olup platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlar için dahili bir standart kullanıyoruz. Ancak bu kodlar karmaşık olduğundan, sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; böylece her zaman beklediğinizi alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için [BCP 47 standardının](https://en.wikipedia.org/wiki/IETF_language_tag) hafifçe değiştirilmiş bir versiyonunu kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Birkaç örnek: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'sından yerel ayar koduyla birlikte bir çağrı aldığında ve bir paywall için ilgili yerelleştirmeyi aramaya başladığında şunlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgilerle (`-`) değiştirilir 2. Ardından tam olarak eşleşen yerel ayar koduna sahip yerelleştirmeyi arayız 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dizeyi alırız (`pt-br` için `pt`) ve eşleşen yerelleştirmeyi arayız 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesini döndürürüz Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yöntem \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, büyük ihtimalle projenizde zaten yerelleştirilmiş string dosyalarıyla çalışıyorsunuzdur. Bu durumda, her bir dosyaya ilgili yerelleştirme için hedeflenen Adapty locale kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtara karşılık gelen değeri şu şekilde çıkarabilirsiniz: ```dart showLineNumbers // 1. app_en.arb, app_es.arb, app_pt_br.arb dosyalarınızı düzenleyin /* app_en.arb */ "adapty_paywalls_locale": "en", /* app_es.arb */ "adapty_paywalls_locale": "es", /* app_pt_br.arb */ "adapty_paywalls_locale": "pt-br", // 2. Locale kodunu çıkarın ve kullanın final locale = AppLocalizations.of(context)!.adapty_paywalls_locale; // locale kodunu AdaptyUI.getViewConfiguration veya Adapty.getPaywall metoduna iletin ``` Bu sayede uygulamanızın her kullanıcısı için hangi yerelleştirmenin alınacağını tam olarak kontrol edebilirsiniz. ## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça yerel ayar kodu tanımlamak yerine benzer (ama özdeş olmayan) sonuçlar elde edebilirsiniz. Bu yaklaşımda, platformun sağladığı başka nesnelerden yerel ayar kodunu çıkarırsınız: ```dart showLineNumbers final locale = Localizations.localeOf(context).languageCode; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşımı önermiyoruz; bunun birkaç nedeni var: 1. iOS'ta tercih edilen diller ile mevcut yerel ayar özdeş değildir. Yerelleştirmenin doğru şekilde seçilmesini istiyorsanız, ya Apple'ın mantığına güvenmeniz gerekir (bu, yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda kutudan çıkar gibi çalışır) ya da bunu kendiniz yeniden oluşturmanız gerekir. 2. Adapty'nin sunucusunun tam olarak ne alacağını öngörmek zordur. Örneğin iOS'ta, bir cihazdan `ar_OM@numbers='latn'` gibi bir yerel ayar elde edip sunucumuza göndermeniz mümkündür. Bu çağrı için aradığınız `ar-om` yerelleştirmesini değil, büyük olasılıkla beklemediğiniz `ar` yerelleştirmesini alırsınız. Yine de bu yaklaşımı kullanmaya karar verirseniz, tüm ilgili kullanım senaryolarını kapsadığınızdan emin olun. </SDKv3> --- # File: flutter-web-paywall --- --- title: "Flutter SDK'da web paywalllarını uygulama" description: "App Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall kurun." --- :::important Başlamadan önce [kontrol panelinde web paywallınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya daha yeni bir sürümünü yüklediğinizden emin olun. ::: Kendi geliştirdiğiniz bir paywall ile çalışıyorsanız, SDK metodunu kullanarak web paywalllarını yönetmeniz gerekir. `.openWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'ı, kullanıcının yönlendirildiği web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü takip eder, ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` metodunu çağırır. Bu sayede ödeme başarılı olup erişim hakları güncellendiğinde, abonelik uygulamada neredeyse anında etkinleşir. ```dart showLineNumbers title="Flutter" try { await Adapty().openWebPaywall(product: <YOUR_PRODUCT>); // The web paywall will be opened } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` :::note `openWebPaywall` metodunun iki versiyonu vardır: 1. `openWebPaywall(product)` — URL'leri paywall'a göre oluşturur ve ürün verilerini de URL'lere ekler. 2. `openWebPaywall(paywall)` — URL'leri paywall'a göre oluşturur ancak ürün verilerini URL'lere eklemez. Adapty paywall'ındaki ürünler web paywall'ındaki ürünlerden farklıysa bunu kullanın. SDK v4'te `paywall` parametresi, getirilen flow'un bir paywall varyasyonu olan `AdaptyFlowPaywall` alır. İndeks kullanmadan önce `flow.paywalls`'ın boş olmadığını kontrol edin; örneğin `flow.paywalls[0]`. ::: #### Hataları yönetme \{#handle-errors\} | Hata | Açıklama | Önerilen işlem | |-----------------------------------------|--------------------------------------------------------------|-----------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Paywall için bir web satın alma URL'si yapılandırılmamış | Paywallın Adapty Kontrol Paneli'nde doğru yapılandırıldığını kontrol edin | | AdaptyError.productWithoutPurchaseUrl | Ürün için bir web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın | | AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun | | AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler düzgün şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimde olduğunu doğrulayın | ## Web paywall'larını uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywall'larını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, web paywall'ları harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sağlamak için web paywall'larını uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanızın içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `in` parametresini `.inAppBrowser` olarak ayarlayın: ```dart showLineNumbers try { await Adapty().openWebPaywall( product: <YOUR_PRODUCT>, openIn: AdaptyWebPresentation.inAppBrowser, ); // The web paywall will be opened in the in-app browser } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` --- # File: flutter-troubleshoot-paywall-builder --- --- title: "Flutter SDK'da Paywall Builder Sorun Giderme" description: "Flutter SDK'da Paywall Builder Sorun Giderme" --- Bu rehber, Flutter SDK'da Adapty Paywall Builder ile tasarlanan paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `createPaywallView` metodu paywall yapılandırmasını alamıyor. **Neden**: Paywall, Paywall Builder'da cihazda gösterim için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Paywall görüntülenme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntülenme sayısı beklenenin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (Flutter SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz; Paywall Builder veya Flow Builder kullanıyorsanız bu, görüntülenme sayısını iki katına çıkarır. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitikler otomatik olarak takip edilir; bu nedenle söz konusu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (Flutter SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder kaynaklı sorunlar yaşıyorsunuz. **Çözüm**: Gerekirse [migration rehberlerini](flutter-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde giderilmiştir. --- # File: flutter-present-flows-in-observer-mode --- --- title: "Flutter SDK'da Observer modunda flow'ları sunma" description: "Flutter uygulamanızda Observer modunda flow'ları ve Paywall Builder paywall'larını sunun; satın almaları kendi kodunuzla yönetin." --- Builder'ı kullanarak bir flow veya paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız, [Flow'ları ve paywall'ları görüntüleme](flutter-present-paywalls) konusuna bakın. ::: :::info Bu özellik Adapty Flutter SDK 4.0 veya sonrasını gerektirir — daha önce yalnızca native iOS ve Android SDK'larında mevcuttu. Yükseltmek için [migration kılavuzuna](migration-to-flutter-sdk-v4) bakın. ::: <details> <summary>Flow'ları sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'yi [App Store ile](initial_ios) ve [Google Play ile](initial-android) ilk entegrasyonunu kurun. 2. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. [Flutter SDK kurulum kılavuzuna](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'lar veya paywalllar yapılandırın](create-paywall) ve bunlara ürün atayın. 5. [Placement'lar oluşturun ve flow'larınızı veya paywalllarınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını çekin](flutter-get-pb-paywalls). </details> Observer modunda SDK, satın alma işlemlerini sizin adınıza gerçekleştirmez. Kullanıcı Adapty tarafından render edilen bir flow veya paywall'da satın alma ya da geri yükleme butonuna dokunduğunda SDK, `AdaptyUIObserverModeResolver`'ınızı çağırır — satın alma veya geri yükleme işlemini orada kendi kodunuzla gerçekleştirin. 1. `AdaptyUIObserverModeResolver`'ı uygulayın: ```dart showLineNumbers title="Flutter" class MyObserverModeResolver extends AdaptyUIObserverModeResolver { @override void observerModeDidInitiatePurchase( AdaptyUIFlowView view, AdaptyPaywallProduct product, void Function() onStartPurchase, void Function() onFinishPurchase, ) { onStartPurchase(); // the view shows its loading indicator // make the purchase with your own code, then: onFinishPurchase(); // the view hides the loading indicator } @override void observerModeDidInitiateRestore( AdaptyUIFlowView view, void Function() onStartRestore, void Function() onFinishRestore, ) { onStartRestore(); // restore purchases with your own code, then: onFinishRestore(); } } ``` `observerModeDidInitiatePurchase` metodu kullanıcının bir satın alma başlattığını, `observerModeDidInitiateRestore` ise kullanıcının bir geri yükleme başlattığını size bildirir. Buna yanıt olarak kendi özel satın alma veya geri yükleme flow'unuzu tetikleyin. Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'a bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi gösterme gibi düzgün flow davranışı için gereklidir: | Callback | Açıklama | | :----------------- | :---------------------------------------------------------------------------------------------- | | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | | onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'a bildirmek için bu callback çağrılmalıdır. | 2. Herhangi bir ekran gösterilmeden önce resolver'ı kaydedin: ```dart showLineNumbers title="Flutter" AdaptyUI().setObserverModeResolver(MyObserverModeResolver()); ``` 3. Flow görünümünü her zamanki gibi oluşturun ve gösterin: [flow'u alın ve görünümünü oluşturun](flutter-get-pb-paywalls), ardından [gösterin](flutter-present-paywalls). Ekstra parametre gerekmez — resolver bir kez kaydedildiğinde, Adapty tarafından render edilen her flow veya paywall, satın alma ve geri yüklemeleri bu resolver üzerinden yönlendirir. :::warning [İşlemi bildirmeyi ve paywall ile ilişkilendirmeyi](report-transactions-observer-mode-flutter) unutmayın. Aksi takdirde Adapty işlemi tanımayacak ve satın almanın kaynak paywall'ını belirleyemeyecektir. ::: --- # File: flutter-quickstart-manual --- --- title: "Flutter SDK'da özel paywall'unuzda satın almaları etkinleştirin" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Flutter paywall'larınıza entegre edin." --- Bu rehber, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall uygulamasının tam kontrolünü elinizde tutarken, Adapty SDK ürünleri getirir, yeni satın almaları gerçekleştirir ve önceki satın almaları geri yükler. Bu rehber Adapty Flutter SDK v4 API'lerini kullanır — v3 kullanıyorsanız, karşılık gelen metod adları için [migration rehberine](migration-to-flutter-sdk-v4) bakın. :::important **Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız, [Adapty Paywall Builder](flutter-quickstart-paywalls)'ı kullanın. Paywall Builder ile kodsuz görsel bir editörde paywall'lar oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan Önce \{#before-you-start\} ### Ürünleri ayarlayın \{#set-up-products\} Uygulama içi satın alımları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywalllar aracılığıyla ulaşılır; bu yapı sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. SDK v4'te bir placement için paywall varyantları bir **flow** nesnesi tarafından taşınır — flow'u çekip ürünlerini sorgularsınız. - [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yapı A/B testleri yürütmeyi ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır. Bu kavramları, kendi özel paywall'unuzla çalışsanız bile anladığınızdan emin olun. Bunlar, temelde uygulamanızda sattığınız ürünleri yönetmenin bir yoludur. Özel paywall'unuzu hayata geçirmek için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu yapı, ürünlerinizi almanızı sağlar. Kontrol panelinde yapmanız gerekenleri anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetme \{#manage-users\} Backend kimlik doğrulaması kullanıp kullanmamak tamamen size bağlıdır. Ancak Adapty SDK, anonim ve kimliği doğrulanmış kullanıcıları farklı şekilde ele alır. Ayrıntıları öğrenmek ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik doğrulama hızlı başlangıç kılavuzunu](flutter-quickstart-identify) okuyun. ## 1. Adım. Ürünleri alın \{#step-1-get-products\} Özel paywallınız için ürünleri almak üzere şunları yapmanız gerekir: 1. [Placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın. 2. Bu flow için ürünler dizisini `getPaywallProducts` metodunu kullanarak alın. ```dart showLineNumbers Future<void> loadPaywall() async { try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); final products = await Adapty().getPaywallProducts(flow: flow); // Use products to build your custom paywall UI } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 2. Satın almaları kabul etme \{#step-2-accept-purchases\} Kullanıcı özel paywallınızdaki bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```dart showLineNumbers Future<void> purchaseProduct(AdaptyPaywallProduct product) async { try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // Purchase successful, profile updated break; case AdaptyPurchaseResultUserCancelled(): // User canceled the purchase break; case AdaptyPurchaseResultPending(): // Purchase is pending (e.g., user will pay offline with cash) break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 3. Satın almaları geri yükle \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik içeren tüm uygulamaların kullanıcılara satın almalarını geri yükleyebilecekleri bir yol sunmasını zorunlu kılar. Kullanıcı geri yükle butonuna bastığında `restorePurchases` metodunu çağırın. Bu işlem, kullanıcının satın alma geçmişini Adapty ile senkronize eder ve güncel profili döndürür. ```dart showLineNumbers Future<void> restorePurchases() async { try { final profile = await Adapty().restorePurchases(); // Restore successful, profile updated } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## Adım 4. Abonelik durumunu kontrol edin \{#step-4-check-the-subscription-status\} Bir satın alma veya geri yükleme işleminin ardından, paywall'ı gösterip göstermeyeceğinize ya da ücretli özellikleri açıp açmayacağınıza karar vermek için kullanıcının [access level](access-level) durumunu kontrol edin. `makePurchase` ve `restorePurchases` metodları zaten güncellenmiş profili döndürür; uygulamanın başka bir yerinde mevcut duruma ihtiyaç duyduğunuzda `getProfile` metodunu kullanın: ```dart showLineNumbers Future<bool> hasPremiumAccess() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['premium']?.isActive ?? false; } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } return false; } ``` Abonelik durumunu kontrol etmenin ve gerçek zamanlı güncellemeleri dinleme dahil izlemenin daha fazla yolu için bkz. [Abonelik durumunu kontrol etme](flutter-check-subscription-status). ## Sonraki adımlar :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada gösterilmeye hazır. Paywall üzerinden test satın alma işlemini tamamlayabildiğinizden emin olmak için [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da satın almalarınızı test edin. Bunun gerçek bir uygulamada nasıl çalıştığını görmek için örnek uygulamamızdaki [PurchasesObserver](https://github.com/adaptyteam/AdaptySDK-Flutter/blob/master/example/lib/purchase_observer.dart)'a göz atabilirsiniz; bu örnekte hata yönetimi, UI gözlemcileri ve kapsamlı SDK entegrasyonuyla birlikte satın alma işleme akışı gösterilmektedir. --- # File: fetch-paywalls-and-products-flutter --- --- title: "Flutter SDK'da remote config paywallları için paywall ve ürünleri getirme" description: "Kullanıcı monetizasyonunu artırmak için Adapty Flutter SDK'da paywall ve ürünleri getirin." --- <SDKv4> Remote config ve özel paywallları sergilemeden önce, bunlarla ilgili bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu lütfen unutmayın. Flow'ları ve Paywall Builder ile özelleştirilmiş paywallları almak için [Flow'ları ve paywallları al](flutter-get-pb-paywalls) bölümüne bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall ve ürün bilgilerini almaya başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri bu paywalla ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-flutter). </details> ## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den gelen ürünlerin bir kombinasyonu olarak işlev görür. Bu çapraz platform ürünler, paywall'lara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri görüntülemek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan koda yazmanız gereken tek ID, placement ID'dir. Paywalllar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir paywall bugün iki ürün, yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini önlemek amacıyla güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywall'lar](flutter-use-fallback-paywalls). Paywall'ları daha hızlı yüklemek için CDN, CDN'e ulaşılamadığı durumlar için ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman paywall'larınızın en güncel sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbellekteki veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.</p> | :::note v4'te `getFlow`, `locale` parametresi almaz. Özel paywalllar için tüm mevcut yerelleştirmeler flow'un remote config'lerinde (`flow.remoteConfigs`) döner — kullanıcının cihaz veya uygulama ayarıyla eşleşeni seçin. Bkz. [Yerelleştirmeler ve locale kodları](flutter-localizations-and-locale-codes). ::: Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Flow'un tanımlayıcılarını (`instanceIdentity`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve remote config'leri (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## Ürünleri getir \{#fetch-products\} Flow'u aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(flow: flow); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısını, ürün adını, fiyatı, para birimini, abonelik süresini ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; tüm mevcut özellikler için bağlantılı belgeye başvurun. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın yerel ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini görüntülemek için `product.price.localizedString` kullanın. Bu yerelleştirme, cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz. Değer yerel para biriminde sağlanır. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (örn. hafta, ay, yıl vb.) görüntülemek için `product.subscription?.localizedPeriod` kullanın. Bu yerelleştirme, cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscription?.period` kullanın. Buradan `unit` enum'una erişerek uzunluğu (gün, hafta, ay, yıl veya bilinmeyen) alabilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin, üç aylık bir abonelik için unit özelliğinde `AdaptyPeriodUnit.month`, numberOfUnits özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Aboneliğin başlangıç teklifi içerdiğini gösteren bir rozet veya başka bir gösterge eklemek için `product.subscription?.offer?.phases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere iki adede kadar indirim aşaması içerebilir. Her aşama nesnesi şu yararlı özellikleri içerir:<br/>• `paymentMode`: `AdaptyPaymentMode.freeTrial`, `AdaptyPaymentMode.payAsYouGo`, `AdaptyPaymentMode.payUpFront` ve `AdaptyPaymentMode.unknown` değerlerine sahip bir enum. Ücretsiz denemeler `AdaptyPaymentMode.freeTrial` türünde olur.<br/>• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarına göre yerelleştirilmiş olarak açıklayan bir dize. Örneğin, üç günlük bir deneme teklifi bu alanda `3 days` olarak gösterilir.<br/>• `subscriptionPeriod`: Alternatif olarak, bu özellikle teklif döneminin ayrıntılarını tek tek alabilirsiniz. Teklifler için önceki bölümde açıklanan şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim abonelik dönemi. | ## Varsayılan kitle flow'u ile flow getirmeyi hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Flow'lar genellikle neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu gidermek için, belirtilen placement'ın **All Users** kitlesi için flow'unu getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-flutter#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi `getFlow` metoduyla flow'u getirmek olduğunu anlamak kritik öneme sahiptir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecekteki) farklı paywalllar göstermeniz gerekiyorsa, çeşitli zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywalllarla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize dayalı hedefleme dahil) kaybettiğiniz anlamına gelir. Bu dezavantajları kabul edip daha hızlı flow çekme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-flutter#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```dart showLineNumbers try { final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); // the requested flow } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum boyunca gereksiz ağ isteklerini önlemek amacıyla güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p> | </SDKv4> <SDKv3> Remote config ve özel paywallları göstermeden önce, bunlara ait bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları çekme konusunda rehberlik için [Paywall Builder paywalllarını ve yapılandırmalarını çekme](flutter-get-pb-paywalls) sayfasına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywallları ve ürünleri çekmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. [Bir paywall oluşturun ve ürünleri paywall'unuza ekleyin](create-paywall) Adapty Kontrol Paneli'nde. 3. [Placement'lar oluşturun ve paywall'unuzu placement'a ekleyin](create-placement) Adapty Kontrol Paneli'nde. 4. [Adapty SDK'yı yükleyin](sdk-installation-flutter) mobil uygulamanıza. </details> ## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'deki ürünlerin bir kombinasyonudur. Bu platformlar arası ürünler, belirli mobil uygulama placement'larında gösterilebilmesi için paywalllarla entegre edilir. Ürünleri görüntülemek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini koda gömmayın.** Koda gömmeniz gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bugün bir paywall iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini göstermeniz gerekir. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.</p><p></p><p>Yerel ayar kodları ve önerilen kullanım şekli hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak verileri sunucudan yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Bu yaklaşımı öneriyoruz çünkü kullanıcılarınızın her zaman en güncel verilere erişmesini sağlar.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanmayı değerlendirin. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerini azaltmak amacıyla oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel olarak temizlendiğinde silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](flutter-use-fallback-paywalls). Ayrıca paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbellekteki veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Ürün ID'lerini koda gömmeyIn! Paywalllar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz denemeler gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Koda gömmeniz gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywallı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özelliklerle birlikte [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirme, cihazın dilini değil, kullanıcının seçtiği mağaza ülkesini baz alır. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın dil ayarlarına göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz. Değer yerel para birimi cinsinden döner. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Periyodu** | Periyodu (ör. hafta, ay, yıl vb.) göstermek için `product.subscription?.localizedPeriod` kullanın. Bu yerelleştirme cihazın diline göre yapılır. Abonelik periyodunu programatik olarak almak için `product.subscription?.period` kullanın. Buradan `unit` enum'una erişerek uzunluğu (yani gün, hafta, ay, yıl veya bilinmiyor) öğrenebilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `AdaptyPeriodUnit.month`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek amacıyla rozet veya başka bir gösterge eklemek için `product.subscription?.offer?.phases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu kullanışlı özellikler bulunur:<br/>• `paymentMode`: `AdaptyPaymentMode.freeTrial`, `AdaptyPaymentMode.payAsYouGo`, `AdaptyPaymentMode.payUpFront` ve `AdaptyPaymentMode.unknown` değerlerine sahip bir enum. Ücretsiz denemeler `AdaptyPaymentMode.freeTrial` türünde olur.<br/>• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemeler için burada `0` arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın diline göre yerelleştirilmiş biçimde açıklayan bir string. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak görünür.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif periyodunun ayrıntılarını bu özellikle alabilirsiniz. Teklifler için bir önceki bölümde açıklanan yöntemle aynı şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının diline göre biçimlendirilmiş indirim abonelik periyodu. | ## Varsayılan kitle paywallıyla veri çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında çekilir, bu nedenle bu işlemi hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall çekme işlemi istediğinizden daha uzun sürebilir. Bu durumlarda, hiç paywall göstermemek yerine kullanıcı deneyimini sorunsuz kılmak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesine ait paywallını getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products-flutter#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywallı çekmek olduğunu göz önünde bulundurun. :::warning Neden `getPaywall` kullanmanızı öneriyoruz? `getPaywallForDefaultAudience` metodunun bazı önemli dezavantajları vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywalllarla sorun yaşamasını kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar, **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, marketing attribution'a veya kendi özel niteliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı paywall çekme işleminden yararlanmak istiyorsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-flutter#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` metodu Flutter SDK 3.2.0 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.</p><p></p><p>Yerel ayar kodları ve önerilen kullanım şekli hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak verileri sunucudan yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Bu yaklaşımı öneriyoruz çünkü kullanıcılarınızın her zaman en güncel verilere erişmesini sağlar.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanmayı değerlendirin. Bu durumda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerini azaltmak amacıyla oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel olarak temizlendiğinde silindiğini unutmayın.</p> | </SDKv3> --- # File: present-remote-config-paywalls-flutter --- --- title: "Flutter SDK'da remote config ile tasarlanan paywallı render etme" description: "Adapty Flutter SDK'da remote config paywalllarını nasıl sunacağınızı keşfedin ve kullanıcı deneyimini kişiselleştirin." --- <SDKv4> Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın koduna render işlemi eklemeniz gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini siz belirlersiniz. Remote config aracılığıyla yapılandırılmış özel paywall'ınızı göstermek için remote config'i çekme yöntemi sunuyoruz; nasıl kullanacağınız tamamen size kalmış. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} v4'te flow, `remoteConfigs` listesi taşır — yapılandırılmış her yerelleştirme için bir remote config. Kullanıcının yerel ayarıyla eşleşen girişi seçin ve gerekli değerleri çıkarın. Doğru yerelleştirmeyi seçmek için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) bölümüne bakın. ```dart showLineNumbers try { final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); // one entry per configured localization; fall back to the first one final config = flow.remoteConfigs.firstWhereOrNull((c) => c.locale == 'en') ?? flow.remoteConfig; final String? headerText = config?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunulur. :::warning Adapty analytics'in huniler ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde paywall görüntüleme olayını kaydettiğinizden emin olun. ::: Paywallı görüntülemeyi tamamladıktan sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](flutter-making-purchases) sayfasını okuyun. [Yedek paywall adı verilen bir yedek paywall oluşturmanızı](flutter-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilecek ve bu durumlarda bile sorunsuz bir deneyim sağlayacaktır. ## Paywall görüntüleme olaylarını takip edin \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da, paywall görüntüleme olaylarını kaydetmek sizin müdahalenizi gerektiriyor; çünkü bir kullanıcının paywall'ı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir paywall görüntüleme olayı kaydetmek için `.logShowFlow(flow: flow)` metodunu çağırmanız yeterli; bu işlem, funnel'larınızdaki ve A/B testlerinizdeki paywall metriklerinize yansıyacaktır. :::important [Builder](adapty-paywall-builder) ile oluşturulan flow'ları veya paywall'ları görüntülüyorsanız `.logShowFlow(flow: flow)` çağrısı yapmanıza gerek yoktur. ::: ```dart showLineNumbers try { await Adapty().logShowFlow(flow: flow); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- |:----------------------------------------------------------------------| | **flow** | zorunlu | Bir `AdaptyFlow` nesnesi. | </SDKv4> <SDKv3> Remote config kullanarak bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulamanızın kodunda görüntüleme işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywalla nelerin dahil edileceğini ve görünümünün nasıl olacağını tamamen siz belirlersiniz. Remote config aracılığıyla yapılandırılmış özel paywallınızı göstermek için uzak yapılandırmayı çekmenizi sağlayan bir metot sunuyoruz. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri çıkarın. ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olarak farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunun. :::warning Adapty analitiğinin huni ve A/B testi için bilgileri yakalayabilmesi amacıyla aşağıda açıklandığı şekilde paywall görüntüleme olayını kaydettiğinizden emin olun. ::: Paywalli görüntüledikten sonra, satın alma akışını ayarlamaya devam edin. Kullanıcı bir satın alma işlemi yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](flutter-making-purchases) bölümünü okuyun. [Yedek paywall adı verilen bir yedek paywall oluşturmanızı](flutter-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilerek bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme etkinliklerini takip edin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplasak da, paywall görüntülemelerini kaydetmek sizin müdahalenizi gerektirir; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilirsiniz. Bir paywall görüntüleme etkinliğini kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu işlem huni ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Paywall builder](adapty-paywall-builder) ile oluşturulan paywallları görüntülüyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesi. | </SDKv3> --- # File: flutter-making-purchases --- --- title: "Flutter SDK ile mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın almaları ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları görüntülemek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak, paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, bu paywall'ları yalnızca göstermek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, bir satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir yöntem kullanmanız gerekir. Bu yöntem, kullanıcıların paywall'larla etkileşime geçmesi ve istedikleri işlemleri gerçekleştirmesi için bir geçit görevi görür. Kullanıcının satın almaya çalıştığı ürün için paywall'ınızda aktif bir promosyon teklifi varsa, Adapty satın alma sırasında bunu otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik olarak uygulanabilmesi için Paywall Builder kullanılarak oluşturulmuş paywall'ları kullanmanız gerektiğini unutmayın. Diğer durumlarda, [iOS'ta başlangıç teklifi uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekecektir. Bu adımı atlamak, yayın sırasında uygulamanızın reddedilmesine yol açabilir. Bunun yanı sıra, başlangıç teklifine hak kazanan kullanıcılardan tam ücret alınmasına neden olabilir. ::: [Başlangıç yapılandırmasını](quickstart) tek bir adımı atlamadan tamamladığınızdan emin olun. Bu olmadan satın almaları doğrulayamayız. ## Satın alma işlemi gerçekleştirme \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın alma işlemleri otomatik olarak gerçekleştirilir; bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlamıyla uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](flutter-implement-paywalls-manually) göz atın. ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve tek seferlik satın almaları hakkında kapsamlı bilgi sağlar.</p><p>Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.</p> | :::warning **Not:** Apple'ın StoreKit sürümü v2.0'ın altında ve Adapty SDK sürümü v2.9.0'ın altında kullanıyorsanız, bunun yerine [Apple App Store paylaşılan sırrı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem şu anda Apple tarafından kullanımdan kaldırılmıştır. ::: ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu işlemin nasıl gerçekleşeceği uygulama mağazasına göre değişir: - App Store'da abonelik, abonelik grubu içinde otomatik olarak güncellenir. Kullanıcı bir gruptan abonelik satın alırken başka bir gruptan aktif aboneliği varsa, her iki abonelik de aynı anda aktif olur. - Google Play'de abonelik otomatik olarak güncellenmez. Geçişi aşağıda açıklandığı şekilde mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka bir abonelikle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```dart showLineNumbers try { final subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( 'OLD_PRODUCT_ID', AdaptyAndroidSubscriptionUpdateReplacementMode.immediateWithTimeProration, ); final result = await Adapty().makePurchase( product: product, parameters: AdaptyPurchaseParameters( subscriptionUpdateParams: subscriptionUpdateParams, ), ); // başarılı çapraz yükseltme } on AdaptyError catch (adaptyError) { // Hatayı işle } catch (e) { // Hatayı işle } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :------- |:--------------------------------------------------------------------------------------------------------| | **parameters** | zorunlu | `subscriptionUpdateParams` alanı bir [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html) nesnesine ayarlanmış `AdaptyPurchaseParameters` nesnesi. | Google Developer belgelerinde abonelikler ve değiştirme modları hakkında daha fazla bilgi edinebilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değiştirme modları için önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değiştirme modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değiştirme modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik faturalandırma dönemi sona erdiğinde gerçekleşir. ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanma sayfasını görüntülemek için: ```dart showLineNumbers try { await Adapty().presentCodeRedemptionSheet(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` :::danger Gözlemlerimize göre, bazı uygulamalarda Teklif Kodu Kullanma sayfası güvenilir şekilde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için aşağıdaki formattaki URL'yi açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ### Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli plan](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin, birkaç aylık yenilenemez bir abonelik), ön ödemeli planlar için [beklemedeki işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleEnablePendingPrepaidPlans(true), ); ``` --- # File: flutter-restore-purchase --- --- title: "Flutter SDK'da mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz bir kullanıcı deneyimi sağlamak için Adapty'de satın almaların nasıl geri yükleneceğini öğrenin." --- Satın Almaları Geri Yükleme, hem iOS hem de Android'de kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden erişmesini sağlayan bir özelliktir. Bu özellik, özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywallarda satın almalar, sizin tarafınızdan ek bir kod gerektirmeksizin otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz. ::: Paywalli özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almaları geri yüklemek için `.restorePurchases()` metodunu çağırın: ```dart showLineNumbers try { final profile = await Adapty().restorePurchases(); if (profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false) { // successful access restore } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------| | **Profile** | <p>Bir [`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi. Bu model, access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir.</p><p>Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.</p> | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: implement-observer-mode-flutter --- --- title: "Flutter SDK'da Observer modunu uygulayın" description: "Adapty'de observer modunu uygulayarak Flutter SDK'da kullanıcı abonelik etkinliklerini takip edin." --- Kendi satın alma altyapınız zaten varsa ve Adapty'ye tamamen geçmeye hazır değilseniz, [Observer mode](observer-vs-full-mode)'u inceleyebilirsiniz. Temel haliyle Observer Mode, gelişmiş analizler ve attribution ile analitik sistemleriyle sorunsuz entegrasyon sunar. Bu ihtiyacınızı karşılıyorsa, yalnızca şunları yapmanız gerekir: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak etkinleştirin. Kurulum talimatları için [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) sayfasına bakın. 2. Mevcut satın alma altyapınızdan Adapty'ye [işlemleri bildirin](report-transactions-observer-mode-flutter). ## Observer modu kurulumu \{#observer-mode-setup\} Satın alma işlemlerini ve abonelik durumunu kendiniz yönetiyorsanız ve Adapty'yi abonelik olayları ile analitik göndermek için kullanıyorsanız Observer modunu etkinleştirin. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle işlemleri kendiniz yönettiğinizden emin olun. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden bir boolean değeri. Varsayılan değer `false`'tur. | ## Observer Mode'da Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer mode'da bazı ek kurulum adımları gerekir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekecek: 1. [Remote config paywall'lar](present-remote-config-paywalls-flutter) için paywall'ları her zamanki gibi gösterin. 3. Satın alma işlemlerini paywall'larla [ilişkilendirin](report-transactions-observer-mode-flutter). :::tip SDK v4'te, Observer mode'da Adapty tarafından render edilen flow'ları ve paywall'ları da sunabilirsiniz: bir kullanıcı ilgili butona dokunduğunda kendi kodunuzla satın alma veya geri yükleme işlemini gerçekleştirmek için bir `AdaptyUIObserverModeResolver` kaydedin. Bkz. [Observer mode'da flow sunma](flutter-present-flows-in-observer-mode). ::: --- # File: report-transactions-observer-mode-flutter --- --- title: "Flutter SDK'da Observer Mode'da işlemleri raporlama" description: "Flutter SDK'da Adapty Observer Mode'da kullanıcı içgörüleri ve gelir takibi için satın alma işlemlerini raporlayın." --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+ (current)" default> Observer mode'da, Adapty SDK kendi başına mevcut satın alma sisteminiz üzerinden yapılan satın almaları takip edemez. App Store'daki işlemleri uygulamanızdan manuel olarak bildirmeniz gerekir. Analitik hatalarını önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız son derece önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanarak açıkça bildirin. :::warning **İşlem bildirmeyi atlama!** `reportTransaction` çağırmazsanız, Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, bir işlem bildirirken `variationId`'yi de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```dart showLineNumbers try { // transaction.finish() her çağrıldığında await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // isteğe bağlı ); } on AdaptyError catch (adaptyError) { // hatayı işle } catch (e) { // hatayı işle } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- | ------------------------------------------------------------ | | transactionId | zorunlu | <ul><li> iOS için: İşlemin tanımlayıcısı.</li><li> Android için: Satın almanın `purchase.getOrderId` string tanımlayıcısı; burada purchase, billing library'nin [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. Bunu [AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x (legacy)" default> Observer modunda, Adapty SDK mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App store'dan işlemleri raporlamanız veya geri yüklemeniz gerekir. Analitik hatalarını önlemek için bunu uygulamanızı yayınlamadan **önce** ayarlamanız kritik önem taşır. Her işlemi açıkça raporlamak için her iki platformda da `reportTransaction` kullanın; Adapty'nin bunu tanımasını sağlamak için Android'de ek bir adım olarak `restorePurchases` kullanın. :::warning **İşlem raporlamayı ve satın alma geri yüklemeyi atlama!** Bu metotları çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, işlem raporlarken `variationId` değerini ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve paywall analizlerinin doğru olmasını sağlar. ```dart showLineNumbers // every time when calling transaction.finish() if (Platform.isAndroid) { try { await Adapty().restorePurchases(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- | ------------------------------------------------------------ | | transactionId | zorunlu | <ul><li> iOS, StoreKit 1 için: bir [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</li><li> iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</li><li> Android için: String tanımlayıcı (satın almanın purchase.getOrderId değeri; burada purchase, billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir).</li></ul> | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. Bunu [AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | </TabItem> <TabItem value="old2" label="Adapty SDK up to 3.2.x (legacy)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **İşlemleri raporlama** - 3.1.x'e kadar olan sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel raporlama gerekmez. - 3.2 sürümü Observer Mode'u desteklemez. </TabItem> <TabItem value="kotlin" label="Android and Android-based cross-platforms" default> **İşlemleri raporlama** [Mobil Kodda Satın Almaları Geri Yükle](flutter-restore-purchase) sayfasında açıklandığı gibi, Observer Mode'da bir işlemi Adapty'ye bildirmek için `restorePurchases` kullanın. :::warning **İşlem bildirmeyi atlama!** `restorePurchases` çağrısı yapmazsanız, Adapty işlemi tanımaz, analytics'te görünmez ve entegrasyonlara gönderilmez. ::: </TabItem> </Tabs> **Paywall'ları işlemlerle ilişkilendirme** Adapty SDK, satın almaları siz işlediğiniz için satın almaların kaynağını belirleyemez. Bu nedenle, Observer mode'da paywall'lar ve/veya A/B testleri kullanmayı planlıyorsanız, uygulama mağazanızdan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Uygulamanızı yayınlamadan önce bunu doğru şekilde ayarlamanız önemlidir; aksi takdirde analizlerde hatalara yol açar. ```dart final transactionId = transaction.transactionIdentifier final variationId = paywall.variationId try { await Adapty().setVariationId('transactionId', variationId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> </Tabs> --- # File: flutter-troubleshoot-purchases --- --- title: "Flutter SDK'da satın alma sorunlarını giderme" description: "Flutter SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, Flutter SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrılıyor ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu durum genellikle eksik Google Play Store kurulumuna veya yapılandırma sorunlarına işaret eder. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## makePurchase iki kez çağrılıyor \{#makepurchase-is-invoked-twice\} **Sorun**: `makePurchase` metodu aynı satın alma için birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya hızlı kullanıcı etkileşimleri nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmalı ya da observer modunda satın almaları kendi tarafınızda yönetmelisiniz. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode-flutter) sayfasına bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan fatura kullanılamıyor hatası alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın kullanılamadığını belirten bir Google Play Billing Library hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store belgelerinde daha fazla bilgi edinebilirsiniz: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamadı \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor şeklinde hatalarla karşılaşıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu yöntem çoğunlukla sandbox ile ilgili satın alma tamamlama işleyicisi sorunlarını çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekirse [taşıma kılavuzlarını](flutter-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüştür. --- # File: flutter-identifying-users --- --- title: "Flutter SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini geliştirmek için kullanıcıları Adapty'de tanımlayın." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi belirlemeniz gerekir. Kullanıcıları Customer User ID'leriyle [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz. ### Yapılandırma sırasında Customer User ID belirleme \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, `.activate()` metoduna `customerUserId` parametresi olarak doğrudan geçirebilirsiniz: ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) ); } catch (e) { // handle the error } ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Yapılandırma sonrasında Customer User ID belirleme \{#setting-customer-user-id-after-configuration\} SDK yapılandırması sırasında kullanıcı ID'niz yoksa, daha sonra istediğiniz zaman `.identify()` metoduyla ayarlayabilirsiniz. Bu metodun en yaygın kullanım senaryoları; kayıt veya oturum açma sonrasında kullanıcı anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçtiğinde ortaya çıkar. ```dart showLineNumbers try { await Adapty().identify(customerUserId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` İstek parametreleri: - **Customer User ID** (zorunlu): string formatında kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerini yeniden gönderme Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahip olabilir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmak için otomatik olarak geçiş yapar. Anonim kullanıcıya özel nitelikler veya üçüncü taraf ağlarından attribution verileri gibi herhangi bir veri iletmişseniz, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden talep etmeniz önemlidir. ::: ### Oturum kapatma ve açma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak istediğiniz zaman kullanıcının oturumunu kapatabilirsiniz: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` Ardından `.identify()` metoduyla kullanıcıyı tekrar oturum açtırabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle birlikte kaydeder, böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulmuş, kararlı bir UUID kullanın ve aynı hesap için cihazlar arasında aynı UUID'yi tekrar kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş olur. Token'ı iki şekilde belirleyebilirsiniz: SDK aktivasyonu sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmeniz gerekir. Yalnızca token'ı geçerseniz, işleme dahil edilmez. ::: ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Gizlenmiş hesap ID'lerini belirleme (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryolarında gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in satın almaları tanımlamasına yardımcı olurken kullanıcı bilgilerini anonim tutar; bu özellikle dolandırıcılığı önleme ve analitik açısından önemlidir. Uygulamanız hassas kullanıcı verileri işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri belirlemeniz gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın almaları takip etmesini sağlar. ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ## Cihazlar arası kullanıcı tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: flutter-setting-user-attributes --- --- title: "Flutter SDK'da kullanıcı özniteliklerini ayarlama" description: "Daha iyi kitle segmentasyonu sağlamak için Adapty'de kullanıcı özniteliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulama kullanıcılarınıza e-posta, telefon numarası gibi isteğe bağlı öznitelikler ekleyebilirsiniz. Bu öznitelikleri kullanarak kullanıcı [segmentleri](segments) oluşturabilir ya da CRM'de görüntüleyebilirsiniz. ### Kullanıcı özniteliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özniteliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setEmail("email@email.com") ..setPhoneNumber("+18888888888") ..setFirstName('John') ..setLastName('Appleseed') ..setGender(AdaptyProfileGender.other) ..setBirthday(DateTime(1970, 1, 3)); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` `updateProfile` metoduyla daha önce ayarladığınız özniteliklerin sıfırlanmayacağını unutmayın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen `<Key>` anahtarları ve `<Value>` değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı öznitelikleri \{#custom-user-attributes\} Kendi özel özniteliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi seviyesi gibi. Bu öznitelikleri segmentlerde hedefli paywall'lar ve teklifler oluşturmak için kullanabilirsiniz; ayrıca hangi ürün metriklerinin geliri en çok etkilediğini bulmak için analizlerde de işe yarar. ```dart showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```dart showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Bazen önceden hangi özel özniteliklerin ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini aklınızda bulundurun; kullanıcı öznitelikleri farklı cihazlardan herhangi bir anda gönderilebileceğinden, sunucudaki öznitelikler son senkronizasyondan bu yana değişmiş olabilir. ::: ### Sınırlamalar \{#limits\} - Kullanıcı başına en fazla 30 özel öznitelik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ve şunlardan herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakterden oluşan bir string veya float olabilir. --- # File: flutter-listen-subscription-changes --- --- title: "Flutter SDK'da abonelik durumunu kontrol etme" description: "Flutter uygulamanızda müşteri tutundurma oranını artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek oldukça kolaydır. Kodunuza manuel olarak ürün ID'leri eklemenize gerek yoktur. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. <details> <summary>Abonelik durumunu kontrol etmeye başlamadan önce (Genişletmek için tıklayın)</summary> - iOS için [App Store Sunucu Bildirimlerini](enable-app-store-server-notifications) yapılandırın - Android için [Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN)](enable-real-time-developer-notifications-rtdn) yapılandırın </details> ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesinin özellikleridir. Uygulamanız başladığında, örneğin [kullanıcıyı tanımlarken](flutter-identifying-users#setting-customer-user-id-on-configuration) profili almanızı ve ardından değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini her seferinde yeniden istek atmadan kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Abonelik durumu güncellemelerini dinleme](flutter-listen-subscription-changes) bölümünde açıklandığı gibi profil değişikliklerini dinleyebilirsiniz. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Sunucudan access level alma \{#retrieving-the-access-level-from-the-server\} Sunucudan access level almak için `.getProfile()` metodunu kullanın: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- | ------------------------------------------------------------ | | Profile | <p>Bir [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) nesnesi. Genellikle, kullanıcının uygulamada premium erişime sahip olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.</p><p></p><p>`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (örneğin internet bağlantısı olmaması), Adapty SDK sunucudan bilgi alamazsa önbellekteki veriler döndürülür. Adapty SDK'nın bilgileri mümkün olduğunca güncel tutmak için `AdaptyProfile` önbelleğini düzenli olarak güncellediğini de belirtmek gerekir.</p> | `.getProfile()` metodu, access level durumunu öğrenebileceğiniz kullanıcı profilini döndürür. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin bir gazete uygulamanız varsa ve farklı konulara abonelikleri bağımsız olarak satıyorsanız, "sports" ve "science" gibi access level'lar oluşturabilirsiniz. Ancak çoğu durumda tek bir access level yeterlidir; bu durumda varsayılan "premium" access level'ını kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: ```dart showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj alabilmek için birkaç ek yapılandırma yapmanız gerekmektedir: ```dart showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adapty ayrıca uygulama başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu erişilemez olsa bile profilin abonelik durumuyla ilgili bilgilere önbellekten ulaşılabilir. Ancak önbellekten doğrudan veri isteği yapılamadığını belirtmek gerekir. SDK, profille ilgili güncellemeleri veya değişiklikleri kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler söz konusu olduğunda, önbellekteki verilerin sunucuyla senkronize kalması için bu değişiklikler önbelleğe gönderilir. --- # File: flutter-deal-with-att --- --- title: "Flutter SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumu ve yönetimini kolaylaştırmak için Flutter'da Adapty'yi kullanmaya başlayın." --- Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama takip yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning Bu değeri, değiştiği anda mümkün olan en kısa sürede göndermenizi kesinlikle öneririz. Ancak bu şekilde veriler, yapılandırdığınız entegrasyonlara zamanında iletilir. ::: --- # File: kids-mode-flutter --- --- title: "Flutter SDK'da Kids Mode" description: "Apple ve Google politikalarına uymak için Kids Mode'u kolayca etkinleştirin. Flutter SDK'da IDFA, GAID veya reklam verisi toplanmaz." --- Flutter uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) ve [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla bu politikaları karşılayacak ve uygulama mağazası incelemelerinden geçecek şekilde yapılandırabilirsiniz. ## Ne yapılması gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdaki verilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunlara ek olarak, customer user ID kullanımında dikkatli olmanızı öneririz. `<Ad.Soyad>` formatındaki bir kullanıcı kimliği, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilir. Kids Mode için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (örneğin hash'lenmiş ID'ler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Kids Mode'u Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde yapılacak güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için kullanıcının IDFA (iOS için), GAID/AAID (Android için) ve IP adresi toplamasını devre dışı bırakın. **Android: SDK yapılandırmanızı güncelleyin** ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') // highlight-start ..withGoogleAdvertisingIdCollectionDisabled(true) // set to `true` ..withIpAddressCollectionDisabled(true), // set to `true` // highlight-end ); } catch (e) { // handle the error } ``` **iOS: SDK v4'te Kids Mode'u Etkinleştirme** :::important SDK v4'te, yerel iOS SDK'sı Swift Package Manager aracılığıyla kurulur ve Kids Mode, IDFA, AdSupport ve AppTrackingTransparency kodlarının tamamını derlemeden çıkaran `KidsMode` Swift paket özelliği aracılığıyla etkinleştirilir. Bu, **Xcode 26** veya daha yeni bir sürüm gerektirir. ::: SDK v4'te, `pubspec.yaml` dosyanızda `adapty_flutter` yerine `adapty_flutter_kids` paketini kullanın. Bu, aynı genel API'ye ve aynı sürüme sahip, eklentinin Kids Mode varyantıdır — tek farkı, yerel iOS SDK'sının `KidsMode` özelliğiyle derlenmesidir: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter_kids: 4.0.0 ``` Dart kodunuz aynı kalır — yalnızca import'u yeni paket adıyla güncelleyin: ```dart showLineNumbers title="Dart" ``` **iOS: CocoaPods kullanarak Kids Mode'u etkinleştirme (SDK v3)** 1. Podfile dosyanızı güncelleyin: - `post_install` bölümünüz **yoksa**, aşağıdaki kod bloğunun tamamını ekleyin. - `post_install` bölümünüz **varsa**, vurgulanan satırları mevcut bölümle birleştirin. ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. Değişiklikleri uygulamak için şunu çalıştırın: ```sh showLineNumbers title="Shell" pod install ``` --- # File: flutter-get-onboardings --- --- title: "Flutter SDK'da onboarding'leri alma" description: "Flutter için Adapty'de onboarding'lerin nasıl alınacağını öğrenin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](flutter-get-pb-paywalls)'ları kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm ve his, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow'ları ve paywall'ları al](flutter-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüle](flutter-present-paywalls) sayfalarına bakın. ::: Adapty Kontrol Paneli'nde builder ile [onboarding'inizin görsel bölümünü tasarladıktan](design-onboarding) sonra, bunu Flutter uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır. Başlamadan önce şunları sağladığınızdan emin olun: 1. [Adapty Flutter SDK](sdk-installation-flutter) sürüm 3.8.0 veya daha yüksek bir sürümü yüklemiş olmalısınız. 2. [Bir onboarding oluşturmuş](create-onboarding) olmalısınız. 3. Onboarding'i bir [placement](placements)'a eklemiş olmalısınız. ## Onboarding'i getirme \{#fetch-onboarding\} No-code builder ile bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirip göstermesi gereken bir yapılandırma içeren container olarak saklanır. Bu container, tüm deneyimi yönetir; hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (sınav yanıtları veya form girişleri gibi) nasıl işleneceğini belirler. Container ayrıca analitik etkinliklerini otomatik olarak takip eder, dolayısıyla ayrı bir görüntüleme takibi uygulamanıza gerek kalmaz. En iyi performans için, onboarding yapılandırmasını erken getirerek görsellerin kullanıcılara gösterilmeden önce indirilmesi için yeterli zaman tanıyın. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboarding(placementId: "YOUR_PLACEMENT_ID"); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` Ardından, göstereceğiniz görünümü almak için `createOnboardingView` metodunu çağırın. :::warning `createOnboardingView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `createOnboardingView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers try { final onboardingView = await Adapty().createOnboardingView(onboarding: onboarding); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` ise Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veriler mevcutsa bunları döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar düzensiz olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e erişilemediğinde kullanılan bağımsız bir yedek sunucu da kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en son sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlandırır. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özelliklerle birlikte bir [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) nesnesi. | ## Varsayılan kitle onboarding'iyle onboarding getirmeyi hızlandırma \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir onboarding getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bu sorunu çözmek için `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz; bu metot, belirtilen placement'ın **All Users** kitlesi için onboarding'i getirir. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Getirme](#fetch-onboarding) bölümünde ayrıntılı olarak açıklandığı gibi `getOnboarding` metoduyla onboarding'i getirmek olduğunu anlamak son derece önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı değerlendirin; çünkü ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlara yol açabilir; ya geriye dönük uyumlu tasarımlar gerektirir ya da eski sürümlerin yanlış görüntülenebileceğini kabul etmek zorunda kalırsınız. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedeflemeyi kaldırır. Kullanım durumunuz için daha hızlı getirme bu dezavantajlardan daha önemliyse, aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |-----------------|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil için, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` ise Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veriler mevcutsa bunları döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar düzensiz olursa olsun daha hızlı yükleme süreleriyle karşılaşırlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e erişilemediğinde kullanılan bağımsız bir yedek sunucu da kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en son sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | --- # File: flutter-present-onboardings --- --- title: "Flutter SDK'da onboarding'leri gösterme" description: "Dönüşümleri artırmak için onboarding'leri etkili biçimde nasıl göstereceğinizi öğrenin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](flutter-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda doğrudan native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları edinin](flutter-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleyin](flutter-present-paywalls) sayfalarına bakın. ::: Builder ile bir onboarding oluşturduysanız, bunu Flutter uygulama kodunuzda kullanıcıya göstermek için ayrıca render etmeniz gerekmez. Bu tür bir onboarding, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. Başlamadan önce şunları kontrol edin: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 veya daha yeni bir sürümü yüklemiş olmanız. 2. Bir [onboarding oluşturmuş](create-onboarding) olmanız. 3. Onboarding'i bir [placement](placements)'a eklemiş olmanız. Adapty Flutter SDK, onboarding'leri sunmak için iki yöntem sunar: - **Bağımsız ekran** - **Gömülü widget** ## Bağımsız ekran olarak göster \{#present-as-standalone-screen\} Bir onboarding'i bağımsız bir ekran olarak görüntülemek için, `createOnboardingView` metoduyla oluşturulan `onboardingView` üzerinde `onboardingView.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Onboarding'i tekrar göstermeniz gerekiyorsa, yeni bir `onboardingView` örneği oluşturmak için `createOnboardingView` metodunu bir kez daha çağırın. :::warning Aynı `onboardingView`'ı yeniden oluşturmadan tekrar kullanmak, `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```dart showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Onboarding'i kapatma \{#dismiss-the-onboarding\} Onboarding'i programatik olarak kapatmanız gerektiğinde `dismiss()` metodunu kullanın: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `AdaptyUIIOSPresentationStyle.fullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.pageSheet` değerlerini kabul eder. ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Widget hiyerarşisine yerleştirme \{#embed-in-widget-hierarchy\} Bir onboarding'i mevcut widget ağacınıza gömmek için `AdaptyUIOnboardingPlatformView` widget'ını doğrudan Flutter widget hiyerarşinizde kullanın. ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Android platform view'ın çalışması için `MainActivity`'nizin `FlutterFragmentActivity`'yi genişlettiğinden emin olun: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## Onboarding sırasında yükleme ekranı \{#loader-during-onboarding\} Bir onboarding sunarken, arka planda görünüm başlatılırken açılış ekranı ile onboarding arasında kısa bir yükleme ekranı görebilirsiniz. Bunu ihtiyacınıza göre farklı şekillerde ele alabilirsiniz. #### onDidFinishLoading kullanarak açılış ekranını kontrol etme \{#control-splash-screen-using-ondidfinishloading\} :::note Bu yaklaşım yalnızca onboarding bir widget olarak yerleştirildiğinde kullanılabilir. Bağımsız ekran sunumu için mevcut değildir. ::: Önerilen platformlar arası yaklaşım, onboarding tam olarak yüklenene kadar splash ekranını veya özel overlay'inizi görünür tutmak, ardından manuel olarak gizlemektir. Gömülü widget kullanırken, kendi widget'ınızı onun üzerine yerleştirin ve `onDidFinishLoading` tetiklendiğinde overlay'i gizleyin: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### Yerel yükleyiciyi özelleştirme \{#customize-native-loader\} :::important Bu yaklaşım platforma özgüdür ve yerel UI kodunun bakımını gerektirir. Uygulamanızda zaten ayrı yerel katmanlar kullanmıyorsanız önerilmez. ::: Varsayılan yükleyiciyi özelleştirmeniz gerekiyorsa platforma özgü layout'larla değiştirebilirsiniz. Bu yaklaşım Android ve iOS için ayrı uygulamalar gerektirir: - **iOS**: Xcode projenize `AdaptyOnboardingPlaceholderView.xib` ekleyin - **Android**: `res/layout` klasöründe `adapty_onboarding_placeholder_view.xml` oluşturun ve burada bir yer tutucu tanımlayın ## Onboarding'lerde bağlantıların nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboarding'lerde bağlantıların nasıl açılacağını özelleştirme özelliği Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboarding'lerdeki bağlantılar uygulama içi tarayıcıda açılır. Bu, web sayfalarını uygulamanızın içinde göstererek kullanıcıların başka bir uygulamaya geçmeden içeriği görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sunar. Bağlantıların bunun yerine harici tarayıcıda açılmasını tercih ediyorsanız, `externalUrlsPresentation` parametresini `AdaptyWebPresentation.externalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: <Tabs> <TabItem value="standalone" label="Bağımsız ekran" default> ```dart showLineNumbers title="Flutter" final onboardingView = await AdaptyUI().createOnboardingView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser ); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="embedded" label="Gömülü widget"> ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` </TabItem> </Tabs> ## Güvenli alan dolgularını devre dışı bırakma (Android) \{#disable-safe-area-paddings-android\} Varsayılan olarak Android cihazlarda, onboarding görünümü durum çubuğu ve gezinme çubuğu gibi sistem UI öğelerinden kaçınmak için güvenli alan dolgularını otomatik olarak uygular. Ancak bu davranışı devre dışı bırakmak ve düzen üzerinde tam kontrol sahibi olmak istiyorsanız, uygulamanıza bir boolean kaynağı ekleyerek bunu yapabilirsiniz: 1. `android/app/src/main/res/values` konumuna gidin. `bools.xml` dosyası yoksa oluşturun. 2. Aşağıdaki kaynağı ekleyin: ```xml <resources> <bool name="adapty_onboarding_enable_safe_area_paddings">false</bool> </resources> ``` Bu değişikliklerin uygulamanızdaki tüm onboarding'ler için geçerli olduğunu unutmayın. --- # File: flutter-handling-onboarding-events --- --- title: "Flutter SDK'da onboarding olaylarını yönetme" description: "Flutter'da Adapty kullanarak onboarding ile ilgili olayları yönetin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](flutter-get-pb-paywalls)'ları kullanın: onboarding'lerin aksine WebView içinde çalışan onboarding'lerden farklı olarak, flow'lar cihazda doğal olarak render edilir — daha akıcı animasyonlar, tutarlı native görünüm ve his, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı olmadan kullanım sunar. Başlamak için [Flow ve paywall'ları al](flutter-get-pb-paywalls) ve [Flow ve paywall'ları göster](flutter-present-paywalls) sayfalarına bakın. ::: Builder ile yapılandırılmış onboarding'ler, uygulamanızın yanıt verebileceği olaylar oluşturur. Bu olayları nasıl işleyeceğiniz, kullandığınız sunum yöntemine bağlıdır: - **Tam ekran sunum**: Tüm onboarding görünümleri için olayları işleyen global bir olay gözlemcisi kurulmasını gerektirir - **Gömülü widget**: Olayları doğrudan widget içindeki satır içi geri çağırma parametreleri aracılığıyla işler Başlamadan önce şunlardan emin olun: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 veya daha yeni bir sürümü yüklediniz. 2. Bir [onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. ## Tam ekran sunum olayları \{#full-screen-presentation-events\} ### Olay gözlemcisini kurma \{#set-up-event-observer\} Tam ekran onboarding'ler için olayları işlemek üzere `AdaptyUIOnboardingsEventsObserver`'ı uygulayın ve sunmadan önce ayarlayın: ```dart showLineNumbers title="Flutter" AdaptyUI().setOnboardingsEventsObserver(this); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Olayları işleme \{#handle-events\} Gözlemcinizde şu metodları uygulayın: ```dart showLineNumbers title="Flutter" void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { // Onboarding finished loading } void onboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error, ) { // Handle loading errors } void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle close action view.dismiss(); } void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle custom actions } void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle user input updates } void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { // Track analytics events } ``` ## Gömülü widget olayları \{#embedded-widget-events\} `AdaptyUIOnboardingPlatformView` kullanırken, olayları doğrudan widget içindeki satır içi callback parametreleri aracılığıyla işleyebilirsiniz. Olayların hem widget callback'lerine hem de global gözlemciye (ayarlandıysa) gönderileceğini, ancak global gözlemcinin isteğe bağlı olduğunu unutmayın: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Onboarding finished loading }, onDidFailWithError: (error) { // Handle loading errors }, onCloseAction: (meta, actionId) { // Handle close action }, onPaywallAction: (meta, actionId) { _openPaywall(actionId); }, onCustomAction: (meta, actionId) { // Handle custom actions }, onStateUpdatedAction: (meta, elementId, params) { // Handle user input updates }, onAnalyticsEvent: (meta, event) { // Track analytics events }, ) ``` ## Olay türleri \{#event-types\} Aşağıdaki bölümler, hangi sunum yaklaşımını kullandığınızdan bağımsız olarak işleyebileceğiniz farklı olay türlerini açıklamaktadır. ### Özel eylemleri işleme \{#handle-custom-actions\} Builder'da bir butona **custom** eylem ekleyip ona bir ID atayabilirsiniz. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ardından bu ID'yi kodunuzda kullanarak özel eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir butona dokunduğunda, `onboardingController` delegate metodu `.custom(id:)` durumuyla tetiklenecek ve `actionId` parametresi builder'daki **Action ID** olacaktır. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```dart // Full-screen presentation void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { switch (actionId) { case 'login': _login(); break; case 'allow_notifications': _allowNotifications(); break; } } // Embedded widget onCustomAction: (meta, actionId) { _handleCustomAction(actionId); } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### Onboarding yüklemesini tamamlama \{#finishing-loading-onboarding\} Bir onboarding yüklemeyi tamamladığında şu olay tetiklenecektir: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { print('Onboarding loaded: ${meta.onboardingId}'); } // Embedded widget onDidFinishLoading: (meta) { print('Onboarding loaded: ${meta.onboardingId}'); } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### Onboarding'i kapatma \{#closing-onboarding\} Bir kullanıcı **Close** eylemi atanmış bir butona dokunduğunda onboarding kapatılmış sayılır. <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Bir kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini görüntülemeyi durdurmanız gerekir. ::: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { await view.dismiss(); } // Embedded widget onCloseAction: (meta, actionId) { Navigator.of(context).pop(); } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### Bir paywall açma \{#opening-a-paywall\} :::tip Bu etkinliği, onboarding içinde bir paywall açmak istiyorsanız işleyin. Eğer paywall kapandıktan sonra açmak istiyorsanız, bunu yapmanın daha doğrudan bir yolu var: kapatma eylemini işleyin ve etkinlik verilerine dayanmadan bir paywall açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, eylem ID'sini bir paywall placement ID'siyle eşit yapmaktır: iOS'ta ekranda aynı anda yalnızca bir görünüm (paywall veya onboarding) görüntülenebilir. Onboarding'in üzerine bir paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışmak paywall'ı kapatacak ve onboarding görünür kalacaktır. Bunu önlemek için, her zaman paywall'ı sunmadan önce onboarding görünümünü kapatın. ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } Future<void> _openPaywall(String actionId) async { // Implement your paywall opening logic here } // Embedded widget onPaywallAction: (meta, actionId) { _openPaywall(actionId); } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### Navigasyonu izleme \{#tracking-navigation\} Onboarding akışı sırasında çeşitli navigasyon ile ilgili olaylar gerçekleştiğinde bir analitik olayı alırsınız: ```dart showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { trackEvent(event.type, meta.onboardingId); } // Embedded widget onAnalyticsEvent: (meta, event) { trackEvent(event.type, meta.onboardingId); } ``` `event` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `onboardingStarted` | Onboarding yüklendiğinde | | `screenPresented` | Herhangi bir ekran gösterildiğinde | | `screenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcıdan gelen yanıt) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `secondScreenPresented` | İkinci ekran gösterildiğinde | | `userEmailCollected` | Kullanıcının e-postası giriş alanı aracılığıyla toplandığında tetiklenir | | `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa, [son ekrana `final` ID'sini atayın](design-onboarding). | | `unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veri) içerir | Her olay şunu içeren `meta` bilgisini barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Mevcut ekranın akıştaki konumu | | `screensTotal` | Akıştaki toplam ekran sayısı | <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: flutter-onboarding-input --- --- title: "Flutter SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Flutter uygulamanızda onboarding verilerini kaydedin ve kullanın." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmış olup gelecekteki bir sürümde tamamen kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](flutter-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall'ları edinme](flutter-get-pb-paywalls) ve [Flow ve paywall'ları görüntüleme](flutter-present-paywalls) bölümlerine bakın. ::: Kullanıcılarınız bir sınav sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde, `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```dart // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Process data } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Process data } ``` Buradaki action formatına [bakın](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyUIOnboardingPlatformView/onStateUpdatedAction.html). <Details> <summary>Her params türü için property şekilleri (genişletmek için tıklayın)</summary> ```dart void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // elementId is a String: elementId; // 'preference_selector' // meta — AdaptyUIOnboardingMeta: meta.onboardingId; // 'onboarding_123' meta.screenClientId; // 'preferences_screen' meta.screenIndex; // 1 meta.screensTotal; // 3 // params is one of the AdaptyOnboardingsStateUpdatedParams subclasses: switch (params) { case AdaptyOnboardingsSelectParams(:final id, :final value, :final label): // a single selected option id; // 'option_1' value; // 'premium' label; // 'Premium Plan' break; case AdaptyOnboardingsMultiSelectParams(:final params): // a list of selected options, each an AdaptyOnboardingsSelectParams params; // [(id: 'interest_1', value: 'sports', label: 'Sports'), (id: 'interest_2', value: 'music', label: 'Music')] break; case AdaptyOnboardingsInputParams(:final input): switch (input) { case AdaptyOnboardingsTextInput(:final value): value; // 'John Doe' break; case AdaptyOnboardingsEmailInput(:final value): value; // 'user@example.com' break; case AdaptyOnboardingsNumberInput(:final value): value; // 25.0 (a double) break; } break; case AdaptyOnboardingsDatePickerParams(:final day, :final month, :final year): day; // 15 month; // 6 year; // 1990 break; } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle anında ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](flutter-setting-user-attributes) girilen verilerle güncellemeniz gerekir. Örneğin, kullanıcılardan `name` ID'sine sahip metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta girmelerini istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```dart showLineNumbers // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` ### Yanıtlara göre paywall'ları özelleştirme \{#customize-paywalls-based-on-answers\} Onboarding'lerde quiz kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywall'ları da özelleştirebilirsiniz. Örneğin, kullanıcılara spor deneyimleri hakkında sorular sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding oluşturucusuna [bir quiz ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler ayarlayın](flutter-setting-user-attributes). ```dart showLineNumbers // Full-screen presentation void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // Embedded widget onStateUpdatedAction: (meta, elementId, params) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` 3. Her özel nitelik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda placement için bir [paywall görüntüleyin](flutter-paywalls). Onboarding'inizde bir paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](flutter-handling-onboarding-events#opening-a-paywall) olarak uygulayın. --- # File: flutter-sdk-call-order --- --- title: "Flutter SDK'da çağrı sırası" description: "Adapty SDK metotlarını doğru sırayla çağırarak kayıp premium erişim, eksik attribution ve aralıklı #2002 hatalarından kaçının." --- `Adapty().activate()` tamamlanmadan diğer hiçbir Adapty SDK metodunu çağıramazsınız. Bu metot çözümlenmeden SDK'nın herhangi bir durumu yoktur. `activate()` ile eş zamanlı ya da daha önce yapılan tüm çağrılar [`#2002 notActivated`](error-handling-on-flutter-react-native-unity#custom-network-codes) hatasıyla sonuçlanır. Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, bu noktada `Adapty().identify()` çağrısını yapın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metotları çağırmayın. Bununla yarışan çağrılar ya [`#3006 profileWasChanged`](error-handling-on-flutter-react-native-unity#custom-network-codes) hatasıyla başarısız olur ya da etkinleştirme sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP kimlikleri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `Adapty().activate` çağrısından önce bunları başlatın ve UID geri çağırımlarını bekleyin. Aksi takdirde MMP kimliği, kısa ömürlü anonim bir profile düşer ve tanımlı profile her zaman aktarılmaz. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıra \{#the-correct-order\} Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK yöntemlerini çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama başlatıldığında müşteri kullanıcı kimliğiniz elinizde varsa, bunu doğrudan `activate()` fonksiyonuna geçirin (adım 2a). Bu yöntem hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gereksizdir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama açılışı, ilk önce | MMP'nin UID callback'ini bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `withCustomerUserId` yapılandırmada ayarlanmış şekilde `Adapty().activate(configuration: ...)` | Uygulama açılışı, 1. adımdan sonra, customer user ID'niz varsa | Önerilen. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `withCustomerUserId` olmadan `Adapty().activate(configuration: ...)` | Uygulama açılışı, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty().setIntegrationIdentifier(key: ..., value: ...)` | 2. adımdan sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için gereklidir. | | 4 | `await Adapty().identify(customerUserId)` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulama ile 2b yolunda | Her zaman `await` kullanın. `identify` sırasında eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar. | | 5 | `getPaywall` (SDK v4'te `getFlow`), `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi takdirde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::important Bu adımları atlamak; geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitleye karşı döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel yüklemeleri \{#web2app-and-web-funnel-installs\} Kullanıcılar web üzerinden ödeme yapıp (Stripe, Paddle) sonradan uygulamayı yüklerse, cihazda ilk çalışan `activate()` yeni bir anonim profil oluşturur. Bu profil, web profiline bağlı değildir. Uygulama açılmadan önce müşteri kullanıcı kimliğini belirleyebiliyorsanız (auth akışınızdan veya install referrer üzerinden), bunu doğrudan `activate()` içine geçirin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` çağrısı yapıp ardından `restorePurchases` çağırana kadar cihazda görünmez. Her web ödemesiyle gönderilecek metadata için şu sayfalara bakabilirsiniz: - [Stripe](stripe) - [Paddle](paddle) --- # File: flutter-optimize-paywall-fetching --- --- title: "Flutter SDK'da paywall çekme işlemini optimize edin" description: "Adapty paywalllarını güvenilir şekilde çekin: Flutter için zamanlama, önbellekleme ve yedek kalıplar." --- Flutter'da güvenilir bir paywall çekme işlemi üç şey yapar: hızlı render eder, kitleye özel paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz bir şekilde yedek davranışa geçer. Aşağıdaki kurallar bunu başarmanın zamanlama, önbellekleme ve yedek kalıplarını kapsar. :::tip Aşağıdaki kurallar, `Adapty().activate()` ve `Adapty().identify()` işlevlerinin zaten tamamlandığını varsayar. Daha fazla bilgi için bkz. [Flutter SDK'da çağrı sırası](flutter-sdk-call-order). ::: Aşağıdaki tavsiyeler v3 metot adlarını kullanmaktadır. SDK v4'te `getPaywall`, `getFlow` olarak; fetch policy türü ise `AdaptyFlowFetchPolicy` olarak yeniden adlandırılmıştır — tüm kurallar değişmeden geçerlidir. ## Kurallar ve dikkat edilmesi gereken noktalar \{#rules-and-pitfalls\} | Bunu yapın | Bunu yapmayın | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı getirin. | Başlatma sırasında tüm placement'ları eş zamanlı olarak önceden getirin. | Toplu önceden getirme işlemi ana iş parçacığını engeller ve yoğunluk sırasında siyah ekrana yol açar. | | `getPaywall`'ı attribution'ın çözülmesine fırsat verdikten sonra çağırın — örneğin `activate`'den 1–2 saniye sonra veya `didUpdateProfileStream` tetiklendikten sonra. | `getPaywall`'ı `runApp`'ten önce `main()` içinde çağırın. | Attribution henüz gelmemiştir. Paywall varsayılan kitleye göre çözümlenir ve segment ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ı süresiz olarak bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf kullanıcılar ağ çözümlenene kadar boş ekran görür ya da uygulamayı kapatır. | [Paywall ve ürünleri getirme](fetch-paywalls-and-products-flutter) sayfasında `fetchPolicy` ve `loadTimeout` parametre referanslarına, [Placement'lar](placements) sayfasında ise doğru placement'ı seçmeye ilişkin bilgilere ulaşabilirsiniz. ## Kötü bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli kötü bağlantı yaşanan pazarlar için (kırsal alanlar, ulaşım güzergahları, yönlendirme sorunlarından etkilenen bölgeler): - İlk fetch dışında her fetch işleminde `fetchPolicy: AdaptyPaywallFetchPolicy.returnCacheDataElseLoad` kullanın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniyeye ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin. - Paywall görüntülemeyi `getProfile()` yanıtına bağlamayın. Yavaş bir profilin arayüzü bloke etmemesi için `getPaywall` işlemini bağımsız olarak çağırın. --- # File: flutter-show-aa-targeted-paywall --- --- title: "Flutter SDK'da ilk açılışta AA hedefli paywall gösterme" description: "Flutter'da ilk açılışta paywall göstermeden önce Apple Ads attribution verisini kısa süre bekleyin; zaman aşımında varsayılan kitleye geri dönün. AdaptyProfile.appliedAttributionSources kullanır." --- Apple Ads (AA) attribution, `Adapty().activate()` çağrısından sonra asenkron olarak gelir. İlk açılışta genellikle henüz gelmemiş olduğundan, hemen `getPaywall` çağırırsanız Adapty isteği varsayılan kitleye göre çözümler ve Apple Ads kullanıcıları AA segmentine özel paywallunuzu göremez. Bir paywallı gösterip sonra değiştirmek yerine, herhangi bir şey göstermeden önce AA attribution'ının gelmesini kısaca bekleyin: attribution kısa bir zaman aşımı içinde gelirse hedeflenmiş paywallı, gelmezse varsayılan kitle paywallını gösterin. `AdaptyProfile.appliedAttributionSources`, AA attribution'ının uygulanıp uygulanmadığını size bildirir. ## Başlamadan önce \{#before-you-start\} İhtiyacınız olanlar: - Adapty Flutter SDK **3.17.0** veya üzeri. - Adapty'de uygulama için yapılandırılmış Apple Ads. Bkz. [Apple Ads](apple-search-ads). ## Nasıl çalışır \{#how-it-works\} `Adapty().activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution verilerini ister ve sonucu Adapty'nin backend'ine iletir. AA, profil için aktif attribution kaynağı haline geldiğinde SDK, `didUpdateProfileStream` dinleyicinize güncellenmiş bir `AdaptyProfile` iletir; bu profil, `appliedAttributionSources` listesinde `AdaptyAttributionSource.appleAds` değerini içerir. İlk başlatmada ele almanız gereken iki olası sonuç vardır: 1. **Attribution zaman aşımı süreniz içinde gelir.** `getPaywall` çağrısı yapın — Adapty isteği Apple Ads kitlesine göre çözümler ve hedeflenmiş paywall'ı döndürür. 2. **Önce zaman aşımı süresi dolar.** Bunun yerine varsayılan kitle paywall'ını gösterin; böylece Apple Ads attribution'ı olmayan kullanıcılar beklemek zorunda kalmaz. `getPaywallForDefaultAudience`, segmentasyon için beklemeden bunu döndürür. `appliedAttributionSources` boş olabilir. Bu şu anlama gelir: - Bu profil için Apple Ads attribution'ı henüz işlenmemiştir veya - hiç attribution gelmemiştir. Her iki durumda da `getPaywallForDefaultAudience` güvenle çağrılabilir — profil durumundan bağımsız olarak varsayılan kitleye ait paywall'ı döndürür. :::important Bekleme yalnızca ilk başlatma için geçerlidir. Apple Ads attribution'ı bir kez kaydedildikten sonra, profilde kalıcı olarak saklanır. Sonraki her başlatmada, önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `AdaptyAttributionSource.appleAds` bilgisini taşır; bu sayede attribution yolu hemen çözümlenir ve `getPaywall` herhangi bir gecikme olmadan Apple Ads segmentine göre paywall'ı döndürür. ::: ## Uygulama \{#implementation\} İlk başlatmada `AdaptyAttributionSource.appleAds` için bekleyin ve katı bir zaman aşımı uygulayın — Apple Ads attribution hiç gelmese de, bu kullanıcıların yine de bir paywall görmesi gerekir. 1. **SDK'yı etkinleştirin.** Bkz. [Flutter SDK'yı yükle ve yapılandır](sdk-installation-flutter). 2. **`Adapty().didUpdateProfileStream.listen(…)` ile profil güncellemelerini dinleyin.** Henüz dinleyiciyi kurmadıysanız bkz. [Abonelik güncellemelerini dinle](flutter-check-subscription-status#listen-to-subscription-updates). 3. **`appliedAttributionSources` içinde `AdaptyAttributionSource.appleAds` değerini bekleyin.** Bu değer göründüğünde `getPaywall` ile paywallı yükleyin — Adapty, AA segmentine uygun varyantı döndürür: ```dart final subscription = Adapty().didUpdateProfileStream.listen((profile) async { if (!profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) return; final paywall = await Adapty().getPaywall(placementId: placementId); // segmentlenmiş paywall'u göster, ardından aboneliği ve zamanlayıcıyı iptal et }); ``` `didUpdateProfileStream` bir broadcast stream'dir ve yeniden oynatma yapmaz; bu nedenle `getProfile()` ile mevcut profili bir kez de doğrudan kontrol edin. Uygulama yeniden başlatıldığında, kaydedilmiş attribution zaten uygulanmış olur ve yeniden emit edilmez. 4. **Abonelikle paralel olarak 3–5 saniyelik bir zamanlayıcı başlatın.** Zamanlayıcı, `AdaptyAttributionSource.appleAds` gelmeden önce tetiklenirse, bunun yerine `getPaywallForDefaultAudience` ile varsayılan kitle paywallını yükleyin. Önce çözümlenen paywallı gösterin ve diğer yolu iptal edin; böylece paywall iki kez çekilmez. Ağ isteği başarısız olursa kullanıcının askıda kalmaması için placement'a bir [yedek paywall](flutter-use-fallback-paywalls) yapılandırın. ## Tam örnek \{#complete-example\} Aşağıdaki uygulama, attribution'ı bir zaman aşımıyla yarıştırır, varsayılan kitle paywall'ını paralelde önceden yükler ve uygun olan paywall'ı döndürür. Çağıran taraf yalnızca tek bir fonksiyonu bekler — çağrı noktasında yönetilecek dinleyici veya durum bayrağı yoktur: - Attribution `timeout` süresi içinde gelirse, `getPaywall` aracılığıyla segmentlere ayrılmış paywall'ı döndürür. - Önce `timeout` süresi dolarsa, `getPaywallForDefaultAudience` aracılığıyla önceden yüklenmiş varsayılan kitle paywall'ını döndürür. ```dart title="apple_ads_paywall.dart" /// Returns the Apple Ads-segmented paywall if attribution is applied within /// [timeout], otherwise the default-audience paywall. Call after Adapty().activate(). Future<AdaptyPaywall> getPaywallOrDefault({ required String placementId, required Duration timeout, }) { // Prefetch the default-audience paywall right away so the timeout path resolves // without an extra network round-trip. `getPaywallForDefaultAudience` skips the // wait for segmentation data. `..ignore()` keeps an unused prefetch from surfacing // as an unhandled error; the error still reaches the caller if this paywall wins. final defaultPaywall = Adapty().getPaywallForDefaultAudience(placementId: placementId)..ignore(); final completer = Completer<AdaptyPaywall>(); late final StreamSubscription<AdaptyProfile> subscription; late final Timer timer; void resolve(Future<AdaptyPaywall> paywall) { if (completer.isCompleted) return; timer.cancel(); subscription.cancel(); completer.complete(paywall); } void onProfile(AdaptyProfile profile) { if (profile.appliedAttributionSources.contains(AdaptyAttributionSource.appleAds)) { resolve(Adapty().getPaywall(placementId: placementId)); } } // Attribution path: react to profile updates as attribution is applied. subscription = Adapty().didUpdateProfileStream.listen(onProfile); // The stream is a broadcast stream and doesn't replay, so check the current // profile too — on relaunches attribution is already stored and won't re-emit. Adapty().getProfile().then(onProfile).ignore(); // Timeout path: fall back to the prefetched default-audience paywall. timer = Timer(timeout, () => resolve(defaultPaywall)); return completer.future; } ``` Splash ekranınızdan çağırın, ardından tamamlandığında paywallı gösterin: ```dart try { final paywall = await getPaywallOrDefault( placementId: 'YOUR_PLACEMENT_ID', timeout: const Duration(seconds: 5), ); // present the paywall } on AdaptyError catch (adaptyError) { // handle the error or show a fallback paywall } catch (e) { // handle the error } ``` `timeout` değerini, kullanıcılarınızı herhangi bir paywall görünmeden önce ne kadar bekletmek istediğinize göre ayarlayın. Kullanıcıların büyük çoğunluğunun Apple Ads attribution verisi olmadığını düşünürsek, hepsi tam timeout süresini bekler; bu yüzden 3 ila 5 saniye makul bir denge noktasıdır. Gelmesi beklenen attribution verisi genellikle uygulama açılışından birkaç saniye içinde ulaşır. Uygulamanız başka amaçlarla (örneğin, [abonelik durumunu kontrol etmek](flutter-check-subscription-status#listen-to-subscription-updates) için) zaten `didUpdateProfileStream`'i dinliyorsa, herhangi bir değişiklik yapmanıza gerek yok. `didUpdateProfileStream` bir broadcast stream olduğundan, birbirinden bağımsız birden fazla dinleyiciyi destekler ve bunları birbirini etkilemeden kullanabilirsiniz. --- # File: flutter-test --- --- title: "Flutter SDK'da test etme ve yayınlama" description: "Adapty ile Flutter uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Flutter uygulamanıza Adapty SDK'yı zaten entegre ettiyseniz, her şeyin doğru şekilde kurulduğunu ve satın almaların hem iOS hem de Android platformlarında beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de Apple'ın sandbox ortamı ve Google Play'in test ortamıyla gerçek satın alma akışını test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almaları kapsamlı şekilde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayına hazırlanma \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesi](release-checklist)'ni takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'ye bildiriliyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanmış --- # File: InvalidProductIdentifiers-flutter --- --- title: "Flutter SDK'da Code-1000 noProductIDsFound Hatası İçin Çözüm" description: "Adapty'de abonelikleri yönetirken oluşan geçersiz ürün tanımlayıcısı hatalarını çözün." --- 1000 kodlu hata olan `noProductIDsFound`, paywall'da talep ettiğiniz ürünlerin App Store'da listelenmesine rağmen satın alma için mevcut olmadığını gösterir. Bu hata bazen `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız görünüyorsa güvenle yok sayabilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız çözmek için aşağıdaki adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin \{#step-3-check-products\} 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümünün altında listelenmiş olarak göreceksiniz. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Tablodaki ürün ID'sini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesiyle karşılaştırın. ID'ler eşleşmiyorsa ürün ID'sini tablodan kopyalayıp Adapty Kontrol Paneli'nde bu ID ile [bir ürün oluşturun](create-product). <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** bölümüne kaydırın ve gereken tüm ülke ve bölgelerin listelendiğini doğrulayın. <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'te **Monetization** → **Subscriptions** bölümüne tekrar gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** bölümüne kaydırın ve **Current Pricing for New Subscribers** bölümünü genişletin. <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Gerekli tüm fiyatların listelendiğinden emin olun. <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. Uygulamanın ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) ana sayfasında **Business**'a tıklayın. <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şirketinizin adını seçin. <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** bölümlerinin hepsinin **Active** olarak göründüğünü doğrulayın. <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayına alabilirsiniz. ## Adım 6. Takılı kaldıysa ürünü yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5. adımların hepsi geçiyor olabilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — ama SDK yine de `1000 noProductIDsFound` döndürüyor olabilir. Bu durumda ürün Apple'ın kayıt defterinde takılı kalmış olabilir. Apple'ın ürün kayıt defteri zaman zaman bir ürünün App Store Connect arayüzünde var olduğu ancak StoreKit arama yoluna açık olmadığı bir duruma girebilir. Ürünü App Store Connect'te silin ve aynı ürün ID'siyle yeniden oluşturun. Yayılma için yeniden oluşturulduktan sonra 24 saate kadar bekleyin. --- # File: cantMakePayments-flutter --- --- title: "Flutter SDK'da Code-1003 cantMakePayment hatasının çözümü" description: "Adapty'de abonelikleri yönetirken ödeme yapma hatasını çözün." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: migration-to-flutter-sdk-v4 --- --- title: "Adapty Flutter SDK'yı v. 4.0'a Geçirin" description: "Adapty Flutter SDK v4.0'a geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty Flutter SDK 4.0, flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı başvuru \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty().getPaywall(placementId: id)` | `Adapty().getFlow(placementId: id)` | | `Adapty().getPaywallForDefaultAudience(placementId: id)` | `Adapty().getFlowForDefaultAudience(placementId: id)` | | `Adapty().getPaywallProducts(paywall: paywall)` | `Adapty().getPaywallProducts(flow: flow)` | | `Adapty().logShowPaywall(paywall: paywall)` | `Adapty().logShowFlow(flow: flow)` | | `AdaptyPaywall` (tür) | `AdaptyFlow` | | `AdaptyPaywallFetchPolicy` (tür) | `AdaptyFlowFetchPolicy` | | `AdaptyUI().createPaywallView(paywall: paywall)` | `AdaptyUI().createFlowView(flow: flow)` | | `AdaptyUIPaywallView` (tür) | `AdaptyUIFlowView` | | `AdaptyUIPaywallPlatformView` (widget) | `AdaptyUIFlowPlatformView` | | `AdaptyUI().presentPaywallView(view)` / `dismissPaywallView(view)` | `AdaptyUI().presentFlowView(view)` / `dismissFlowView(view)` | | `AdaptyUIPaywallsEventsObserver` | `AdaptyUIFlowsEventsObserver` | | `AdaptyUI().setPaywallsEventsObserver(observer)` | `AdaptyUI().setFlowsEventsObserver(observer)` | | `paywallViewDid*` callback'leri | `flowViewDid*` callback'leri | | `paywallViewDidFailRendering` | `flowViewDidReceiveError` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` artık bir `AdaptyFlow` alır. Bir flow çekerken artık `locale` geçirmenize gerek yoktur. Satın alma ve profil API'leri (`makePurchase`, `restorePurchases`, `getProfile`, `identify` vb.) değişmeden kalmıştır; `present`, `dismiss` ve `showDialog` view metodları da aynı şekilde. Bazı varsayılan davranışlar değişti — bkz. [Varsayılan davranış değişiklikleri](#default-behavior-changes). ## Minimum sürümler \{#minimum-versions\} Adapty Flutter SDK 4.0, minimum gereksinimleri yükseltiyor: - **iOS 15.0** — minimum iOS deployment target, iOS 13.0'dan yükseltildi. - **Xcode 26** veya daha yenisi — yerel iOS SDK'sı Swift tools 6.2 kullanıyor. - **Flutter 3.32.0** (Dart 3.8.0) veya daha yenisi. ## Kurulum \{#installation\} ### Paketi güncelleyin \{#update-the-package\} Hangi paketi yükleyeceğiniz, uygulamanızın Kids Mode kullanıp kullanmadığına bağlıdır. Çoğu uygulama için `pubspec.yaml` dosyanızda `adapty_flutter` paketini v4.0'a güncelleyin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: 4.0.0 ``` Uygulamanız Kids Mode kullanıyorsa bunun yerine `adapty_flutter_kids` belirtin: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter_kids: 4.0.0 ``` Bu **bağımsız** paket, App Store gereksinimlerine uymak için IDFA ve reklam takip kodlarını kaldırır. Dart import yolunu `package:adapty_flutter_kids/adapty_flutter.dart` olarak güncelleyin. Bunun dışında, migration işlemi normal paketle tamamen aynıdır. Kids Mode ayrıca Adapty Kontrol Paneli'nde IP adresi toplamanın devre dışı bırakılmasını gerektirir — tam kurulum için [Kids Mode](kids-mode-flutter) sayfasına bakın. ### iOS: yerel SDK'lar artık Swift Package Manager üzerinden geliyor \{#ios-native-sdks-now-come-through-swift-package-manager\} [CocoaPods'ın spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), bu nedenle v4 itibarıyla yerel iOS SDK'sı **artık CocoaPods üzerinden dağıtılmıyor** — eklenti bunu yalnızca **Swift Package Manager** aracılığıyla çekiyor. Flutter 3.32–3.43 kullanıyorsanız, Swift Package Manager desteğini bir kez etkinleştirin: ```bash flutter config --enable-swift-package-manager ``` Flutter 3.44 ve sonrası Swift Package Manager'ı varsayılan olarak etkinleştiriyor, dolayısıyla bu sürümlerde herhangi bir işlem yapmanıza gerek yok. ## Flow'ları getirme \{#fetching-flows\} ### getPaywall → getFlow Dönen tür `AdaptyPaywall` yerine `AdaptyFlow` olarak değişti ve artık `locale` parametresi geçmiyorsunuz — bir flow render ettiğinizde yerelleştirme otomatik olarak çözümlenir; özel paywalllar için yapılandırılmış tüm locale'lar `flow.remoteConfigs` içinde döner: ```diff showLineNumbers - final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID', locale: 'en'); + final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); ``` `getPaywallForDefaultAudience` da aynı şekilde yeniden adlandırıldı: ```diff showLineNumbers - final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID', locale: 'en'); + final flow = await Adapty().getFlowForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); ``` Fetch policy türü `AdaptyPaywallFetchPolicy`'den `AdaptyFlowFetchPolicy`'ye yeniden adlandırıldı; seçenekleri (`reloadRevalidatingCacheData`, `returnCacheDataElseLoad`, `returnCacheDataIfNotExpiredElseLoad`) değişmedi. ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` adını korur ancak artık `flow` parametresi aracılığıyla bir `AdaptyFlow` alır: ```diff showLineNumbers - final products = await Adapty().getPaywallProducts(paywall: paywall); + final products = await Adapty().getPaywallProducts(flow: flow); ``` ## Veri modeli \{#data-model\} `getFlow`, `AdaptyPaywall` yerine bir `AdaptyFlow` döndürür ve nesne yapısı değişti: | v3 `AdaptyPaywall` üyesi | v4 `AdaptyFlow` üyesi | İşlem | |---|---|---| | `remoteConfig` (tekil, nullable) | `remoteConfigs` (liste) | Bir flow, yapılandırılmış her dil için bir remote config taşır. `remoteConfig` getter'ı hâlâ mevcuttur ve ilk girişi döndürür; belirli bir dil seçmek için `remoteConfigs` içinde `locale` değerine göre arama yapın. | | `productIdentifiers` | `productIdentifiers` | Korundu, ancak artık flow'un tüm paywall varyasyonlarından derleniyor. Varyasyon bazındaki tanımlayıcılar `flow.paywalls[i].productIdentifiers` üzerinde bulunur. | | `hasViewConfiguration` | `hasViewConfiguration` | Değişmedi. | | `placementId` (kullanımdan kalktı) | kaldırıldı | `flow.placement.id` kullanın. | | `revision` (kullanımdan kalktı) | kaldırıldı | `flow.placement.revision` kullanın. | | `vendorProductIds` (kullanımdan kalktı) | kaldırıldı | `productIdentifiers` kullanın. | | _(yeni)_ | `paywalls` (`AdaptyFlowPaywall` listesi) | Her giriş, flow içindeki bir paywall varyasyonunu temsil eder ve kendine ait `name`, `variationId` ve `productIdentifiers` değerlerine sahiptir. | `AdaptyPaywallViewConfiguration` artık açık değil — görünüm yapılandırması artık opak. Bu türe yapılan tüm referansları kaldırın. ## Web paywall metodları \{#web-paywall-methods\} `openWebPaywall` ve `createWebPaywallUrl` isimlerini korur, ancak `paywall` parametresi artık `AdaptyPaywall` yerine `AdaptyFlowPaywall` (bir flow varyasyonu) alır. Yine de bunun yerine `AdaptyPaywallProduct` geçirebilirsiniz. ```diff showLineNumbers final flow = await Adapty().getFlow(placementId: 'YOUR_PLACEMENT_ID'); - await Adapty().openWebPaywall(paywall: paywall); + if (flow.paywalls.isNotEmpty) { + await Adapty().openWebPaywall(paywall: flow.paywalls[0]); + } ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık bir `AdaptyFlow` alıyor. Olay aynı varyasyon üzerinden kaydedilmeye devam eder; bu sayede mevcut funnel ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapmadan çalışmayı sürdürür. ```diff showLineNumbers - await Adapty().logShowPaywall(paywall: paywall); + await Adapty().logShowFlow(flow: flow); ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülerken bu metodu çağırmanıza gerek yoktur — Adapty bu görüntülemeleri otomatik olarak takip eder. ## Flow'ları görüntüleme \{#displaying-flows\} ### createPaywallView → createFlowView Metodu yeniden adlandırın ve `AdaptyFlow`'u `flow` parametresi aracılığıyla geçirin. Diğer parametreler (`loadTimeout`, `preloadProducts`, `customTags`, `customTimers`, `customAssets`, `productPurchaseParams`) ve view metodları `present`, `dismiss` ve `showDialog` değişmeden kalır: ```diff showLineNumbers - final view = await AdaptyUI().createPaywallView(paywall: paywall); + final view = await AdaptyUI().createFlowView(flow: flow); await view.present(); ``` ### AdaptyUIPaywallView → AdaptyUIFlowView Görünüm türü yeniden adlandırıldı. Kullanımdan kaldırılmış `paywallVariationId` özelliği kaldırıldı — bunun yerine `variationId` kullanın: ```diff showLineNumbers - void flowViewDidAppear(AdaptyUIPaywallView view) { + void flowViewDidAppear(AdaptyUIFlowView view) { ``` ### AdaptyUIPaywallPlatformView → AdaptyUIFlowPlatformView Görünümü widget ağacınıza widget olarak gömmek istiyorsanız, adını değiştirin ve `flow` parametresini geçin. Olay callback'leri (`onDidAppear`, `onDidFinishPurchase` vb.) aynı isimlerini korur: ```diff showLineNumbers - AdaptyUIPaywallPlatformView( - paywall: paywall, + AdaptyUIFlowPlatformView( + flow: flow, onDidFinishPurchase: (view, product, purchaseResult) { /* … */ }, ) ``` :::note `createFlowView` ile oluşturulan bir flow görünümü tek kullanımlıktır: `dismiss()` çağrıldıktan sonra görünüm bellekten serbest bırakılır ve bir daha gösterilemez — flow'u tekrar göstermek için `createFlowView`'ı yeniden çağırın. ::: ## Olayları Yönetme \{#handling-events\} Observer sınıfı `AdaptyUIPaywallsEventsObserver`'dan `AdaptyUIFlowsEventsObserver`'a, kayıt metodu `setPaywallsEventsObserver`'dan `setFlowsEventsObserver`'a ve tüm `paywallViewDid*` callback'leri `flowViewDid*`'e yeniden adlandırıldı: ```diff showLineNumbers - class MyObserver extends AdaptyUIPaywallsEventsObserver { + class MyObserver extends AdaptyUIFlowsEventsObserver { @override - void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { + void flowViewDidPerformAction(AdaptyUIFlowView view, AdaptyUIAction action) { // … } } - AdaptyUI().setPaywallsEventsObserver(this); + AdaptyUI().setFlowsEventsObserver(this); ``` Artık üç callback **zorunludur** — bunlar olmadan observer'ınız derlenmez: - **`flowViewDidFinishPurchase`**: v3'te isteğe bağlıydı; varsayılan davranış satın alma sonrasında görünümü kapatıyordu. Artık ne olacağına siz karar veriyorsunuz: flow'a devam edin ya da `view.dismiss()` çağırın. - **`flowViewDidFinishRestore`**: v3'te olduğu gibi zorunludur. - **`flowViewDidReceiveError`**: `paywallViewDidFailRendering` yerine gelir ve artık diğer görünüm hatalarını da alır. İki küçük değişiklik daha: - `setFlowsEventsObserver` (ve `setOnboardingsEventsObserver`) artık önceden ayarlanmış bir observer'ı ayırmak için `null` kabul ediyor; bu sayede SDK artık onu tutmuyor. - Yeni isteğe bağlı `flowViewDidReceiveAnalyticEvent` callback'i, bir flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmiyor, dolayısıyla bunu uygulamanız gerekmiyor. v4 ayrıca isteğe bağlı olarak kullanabileceğiniz yeni özellikler ekliyor: - `AdaptyUI().setObserverModeResolver(...)` ile birlikte `AdaptyUIObserverModeResolver` — SDK [Observer mode](implement-observer-mode-flutter) olarak çalışırken flow'lardan başlatılan satın alma ve geri yüklemeleri yönetir. Daha önce bu yalnızca native iOS ve Android SDK'larında kullanılabiliyordu. Bkz. [Flow'ları Observer mode'da sunma](flutter-present-flows-in-observer-mode). - `AdaptyUI().setSystemRequestsHandler(...)` ile birlikte `AdaptyUISystemRequestsHandler` — bir flow'dan gelen sistem istekleri (işletim sistemi izin istemleri ve App Store inceleme istekleri) için ayrılmıştır. Flow'lar henüz bu istekleri tetiklemediğinden bir handler kaydetmeniz gerekmez. ## Kaldırılan API'lar \{#removed-apis\} Bu semboller 3.x sürümünde kullanımdan kaldırılmıştı ve v4'te tamamen kaldırılmıştır: ### setFallbackPaywalls → setFallback ```diff showLineNumbers - await Adapty().setFallbackPaywalls(assetId); + await Adapty().setFallback(assetId); ``` ### withIdfaCollectionDisabled → withAppleIdfaCollectionDisabled ```diff showLineNumbers configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') - ..withIdfaCollectionDisabled(true), + ..withAppleIdfaCollectionDisabled(true), ``` ### Kaldırılan diğer üyeler \{#other-removed-members\} - **`AdaptyPurchaseResultSuccess.jwsTransaction`**: `appleJwsTransaction` kullanın. - **`AdaptyUIFlowView.paywallVariationId`**: `variationId` kullanın. - **`AdaptyUIObserver` ve `AdaptyUI().setObserver(...)`**: `AdaptyUIFlowsEventsObserver` ve `setFlowsEventsObserver(...)` kullanın. ## Varsayılan davranış değişiklikleri \{#default-behavior-changes\} Bu değişiklikler derleme hatası oluşturmaz, bu nedenle çalışma zamanında test edin: - **Başarılı satın alma**: v3'te varsayılan `paywallViewDidFinishPurchase` görünümü kapatıyordu. v4'te `flowViewDidFinishPurchase` zorunludur ve varsayılan davranışı yoktur — bu davranışı istiyorsanız görünümü kendiniz kapatın. - **Android sistem geri tuşu**: Artık varsayılan olarak bir flow'u kapatmaz. Eylem, `AndroidSystemBackAction` olarak `flowViewDidPerformAction`'a iletilir — geri tuşunun flow'u kapatmasını istiyorsanız bunu orada ele alın. - **URL açma**: Varsayılan `flowViewDidPerformAction` artık `OpenUrlAction`'ı URL'yi yerel olarak açarak işler (kontrol panelindeki uygulama içi veya harici tarayıcı ayarına uyar); `CloseAction`'da ise görünümü kapatmaya devam eder. URL'leri kendiniz işlemek istiyorsanız callback'i geçersiz kılın. - **Görünüm hataları**: `flowViewDidReceiveError` zorunludur ve kapatma işlemi sizin implementasyonunuza bağlıdır. v3 entegrasyonunuz render hatalarında görünümün otomatik olarak kapanmasına dayanıyorsa, bu callback içinde `view.dismiss()` çağırın. - **Görünüm yaşam döngüsü**: Bir flow veya onboarding görünümünü kapatmak, onu bellekten serbest bırakır. Kapatılmış bir görünüm artık yeniden gösterilemez — bunun yerine yeni bir tane oluşturun. ## Onboarding API'sinin kullanımdan kaldırılması \{#onboarding-api-deprecation\} Eski onboarding API'si, v4.0'da [Flow Builder](adapty-flow-builder) lehine kullanımdan kaldırılmıştır. Çalışmaya devam etmektedir; IDE'niz `@Deprecated` anotasyonları aracılığıyla kullanımdan kaldırılan sembolleri işaretler — çalışma zamanında herhangi bir uyarı gösterilmez. Bu semboller gelecekteki bir sürümde kaldırılacağından, onboarding'lerinizi Flow Builder'a taşımayı planlamanız önerilir. Kullanımdan kaldırılan semboller: `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView`, `presentOnboardingView`, `dismissOnboardingView`, `setOnboardingsEventsObserver`, `AdaptyOnboarding`, `AdaptyUIOnboardingView`, `AdaptyUIOnboardingPlatformView`, `AdaptyUIOnboardingsEventsObserver` ve onboarding durum, girdi ile analitik modelleri. --- # File: flutter-migration-guide-310 --- --- title: "Flutter Adapty SDK 3.10.0 için Geçiş Rehberi" description: "" --- Adapty SDK 3.10.0, bazı geliştirmeler içeren büyük bir sürümdür. Bu değişiklikler için aşağıdaki geçiş adımlarını uygulamanız gerekebilir: 1. `makePurchase` metodunu, tek tek parametreler yerine `AdaptyPurchaseParameters` kullanacak şekilde güncelleyin. 2. `AdaptyPaywall` modelinde `vendorProductIds` yerine `productIdentifiers` kullanın. ## makePurchase metodunu güncelleyin \{#update-makepurchase-method\} `makePurchase` metodu artık ayrı ayrı `subscriptionUpdateParams` ve `isOfferPersonalized` argümanları yerine `AdaptyPurchaseParameters` kullanıyor. Bu değişiklik daha iyi tip güvenliği sağlar ve satın alma parametrelerinin gelecekte genişletilmesine olanak tanır. ```diff showLineNumbers - final purchaseResult = await adapty.makePurchase( - product: product, - subscriptionUpdateParams: subscriptionUpdateParams, - isOfferPersonalized: true, - ); + final parameters = AdaptyPurchaseParametersBuilder() + ..setSubscriptionUpdateParams(subscriptionUpdateParams) + ..setIsOfferPersonalized(true) + ..setObfuscatedAccountId('your-account-id') + ..setObfuscatedProfileId('your-profile-id'); + final purchaseResult = await adapty.makePurchase( + product: product, + parameters: parameters.build(), + ); ``` Ek parametreye ihtiyaç duymuyorsanız şu şekilde kullanabilirsiniz: ```dart showLineNumbers final purchaseResult = await adapty.makePurchase( product: product, ); ``` ## AdaptyPaywall model kullanımını güncelleyin \{#update-adaptyapaywall-model-usage\} `vendorProductIds` özelliği kullanımdan kaldırılmış olup yerini `productIdentifiers` almıştır. Yeni özellik, düz string'ler yerine `AdaptyProductIdentifier` nesneleri döndürerek daha yapılandırılmış ürün bilgisi sunar. ```diff showLineNumbers - paywall.vendorProductIds.map((vendorId) => - ListTextTile(title: vendorId) - ).toList() + paywall.productIdentifiers.map((productId) => + ListTextTile(title: productId.vendorProductId) + ).toList() ``` `AdaptyProductIdentifier` nesnesi, `vendorProductId` özelliği aracılığıyla vendor ürün kimliğine erişim sağlar; mevcut işlevselliği korurken gelecekteki geliştirmeler için daha iyi bir yapı sunar. ## Geriye dönük uyumluluk \{#backward-compatibility\} Her iki değişiklik de geriye dönük uyumluluğu korumaktadır: - `makePurchase` içindeki eski parametreler kullanımdan kaldırılmış olsa da çalışmaya devam eder - `vendorProductIds` özelliği kullanımdan kaldırılmış olsa da erişilebilir olmaya devam eder - Mevcut kodunuz çalışmaya devam eder; ancak deprecation uyarıları göreceksiniz Gelecekteki uyumluluğu sağlamak ve geliştirilmiş tip güvenliği ile genişletilebilirlikten yararlanmak için kodunuzu yeni API'leri kullanacak şekilde güncellemenizi öneririz. --- # File: flutter-migration-guide-38 --- --- title: "Adapty Flutter SDK'yı v. 3.8'e Geçirme" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Flutter SDK v3.8'e geçin." --- Adapty SDK 3.8.0, bazı iyileştirmeler getiren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Observer sınıfı ve metod adlarını güncelleyin. 2. Yedek paywall metod adını güncelleyin. 3. Olay işleme metodlarındaki view sınıf adını güncelleyin. ## Observer sınıfı ve metod adlarını güncelleme \{#update-observer-class-and-method-names\} Observer sınıfı ve kayıt metodu yeniden adlandırıldı: ```diff showLineNumbers - class MyObserver extends AdaptyUIObserver { + class MyObserver extends AdaptyUIPaywallsEventsObserver { @override void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { // Handle action } } // Register observer - AdaptyUI().setObserver(this); + AdaptyUI().setPaywallsEventsObserver(this); ``` ## Yedek paywall metod adını güncelleme \{#update-fallback-paywalls-method-name\} Yedek paywall ayarlama metodu basitleştirildi: ```diff showLineNumbers try { - await Adapty.setFallbackPaywalls(assetId); + await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Olay işleme yöntemlerinde view sınıfı adını güncelleme \{#update-view-class-name-in-event-handling-methods\} Tüm olay işleme yöntemleri artık `AdaptyUIView` yerine yeni `AdaptyUIPaywallView` sınıfını kullanıyor: ```diff showLineNumbers - void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) + void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) - void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile) + void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile) - void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error) + void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) - void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile) + void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) - void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) - void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) + void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) - void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) ``` --- # File: migration-to-flutter-sdk-34 --- --- title: "Adapty Flutter SDK'yı v3.4'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Flutter SDK v3.4'e geçiş yapın." --- Adapty SDK 3.4.0, sizin tarafınızda geçiş adımları gerektiren iyileştirmeler sunan önemli bir sürümdür. ## Yedek paywall dosyalarını güncelleme \{#update-fallback-paywall-files\} Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki [mevcut yedek paywall'ları yeni dosyalarla değiştirin](flutter-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleme \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Daha önce, işlemleri Adapty'ye bildirmek için farklı yöntemler kullanılıyordu. Yeni sürümde, `reportTransaction` yöntemi hem Android hem de iOS'ta tutarlı biçimde kullanılmalıdır. Bu yöntem, her işlemi Adapty'ye açıkça bildirir ve tanınmasını sağlar. Bir paywall kullanıldıysa, işlemi ilgili paywall'a bağlamak için varyasyon ID'sini geçirin. :::warning **İşlem bildirmeyi atlamayın!** `reportTransaction` çağrısını yapmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - // every time when calling transaction.finish() - if (Platform.isAndroid) { - try { - await Adapty().restorePurchases(); - } on AdaptyError catch (adaptyError) { - // handle the error - } catch (e) { - } - } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter330 --- --- title: "Adapty Flutter SDK'yı v3.3'e Geçirme" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty Flutter SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.0, bazı iyileştirmeler içeren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Yedek paywall sağlama yöntemini güncelleyin. 2. `getProductsIntroductoryOfferEligibility` metodunu kaldırın. 3. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. 4. Observer mode uygulamasını güncelleyin. ## Yedek paywall sağlama yöntemini güncelleyin \{#update-method-for-providing-fallback-paywalls\} Daha önce bu yöntem, yedek paywall'u JSON dizesi (`jsonString`) olarak alıyordu; artık bunun yerine yerel yedek dosyanın yolunu (`assetId`) alıyor. ```diff showLineNumbers import 'dart:async' show Future; import 'dart:io' show Platform; -import 'package:flutter/services.dart' show rootBundle; -final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; -final jsonString = await rootBundle.loadString(filePath); +final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { - await adapty.setFallbackPaywalls(jsonString); + await adapty.setFallbackPaywalls(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Tam kod örneği için [Yedek paywall kullanımı](flutter-use-fallback-paywalls) sayfasına bakın. ## `getProductsIntroductoryOfferEligibility` metodunu kaldırın \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 öncesinde, ürün nesnesi kullanıcının uygun olup olmadığından bağımsız olarak her zaman teklifleri içeriyordu. Teklifi kullanmadan önce uygunluğu manuel olarak kontrol etmeniz gerekiyordu. Artık ürün nesnesi yalnızca kullanıcı uygunsa bir teklif içeriyor. Bu da uygunluğu ayrıca kontrol etmenize gerek kalmadığı anlamına gelir; bir teklif varsa kullanıcı zaten uygundur. ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleyin \{#update-third-party-integration-sdk-configuration\} Adapty Flutter SDK 3.3.0 ve sonrasında entegrasyonların düzgün çalışması için aşağıdaki bölümlerde açıklandığı gibi SDK yapılandırmalarınızı güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. ```diff showLineNumbers import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_config.dart'; try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } + await Adapty().setIntegrationIdentifier( + key: "adjust_device_id", + value: adid, + ); final attributionData = await Adjust.getAttribution(); var attribution = Map<String, String>(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; - Adapty().updateAttribution( - attribution, - source: AdaptyAttributionSource.adjust, - networkUserId: adid, - ); + await Adapty().updateAttribution(attribution, source: "adjust"); } catch (e) { // handle the error } on AdaptyError catch (adaptyError) { // handle the error } ``` ### AirBridge Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge) sayfasına bakın. ```diff showLineNumbers import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart'; final deviceUUID = await Airbridge.state.deviceUUID; try { - final builder = AdaptyProfileParametersBuilder() - ..setAirbridgeDeviceId(deviceUUID); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "airbridge_device_id", + value: deviceUUID, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) sayfasına bakın. ```diff showLineNumbers import 'package:amplitude_flutter/amplitude.dart'; final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); final deviceId = await amplitude.getDeviceId(); final userId = await amplitude.getUserId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setAmplitudeDeviceId(deviceId) - ..setAmplitudeUserId(userId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "amplitude_user_id", + value: userId, + ); + await Adapty().setIntegrationIdentifier( + key: "amplitude_device_id", + value: deviceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### AppMetrica Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppMetrica entegrasyonu için SDK yapılandırması](appmetrica#sdk-configuration) sayfasına bakın. ```diff showLineNumbers import 'package:appmetrica_plugin/appmetrica_plugin.dart'; final deviceId = await AppMetrica.deviceId; if (deviceId != null) { try { - final builder = AdaptyProfileParametersBuilder() - ..setAppmetricaDeviceId(deviceId) - ..setAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceId, + ); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID", + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) sayfasına bakın. ```diff showLineNumbers import 'package:appsflyer_sdk/appsflyer_sdk.dart'; AppsflyerSdk appsflyerSdk = AppsflyerSdk(<YOUR_OPTIONS>); appsflyerSdk.onInstallConversionData((data) async { try { final appsFlyerUID = await appsFlyerSdk.getAppsFlyerUID(); - await Adapty().updateAttribution( - data, - source: AdaptyAttributionSource.appsflyer, - networkUserId: appsFlyerUID, - ); + await Adapty().setIntegrationIdentifier( + key: "appsflyer_id", + value: appsFlyerUID, + ); + + await Adapty().updateAttribution(data, source: "appsflyer"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } }); appsflyerSdk.initSdk( registerConversionDataCallback: true, registerOnAppOpenAttributionCallback: true, registerOnDeepLinkingCallback: true, ); ``` ### Branch Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırması](branch#connect-your-app-to-branch) sayfasına bakın. ```diff showLineNumbers FlutterBranchSdk.initSession().listen((data) async { try { + await Adapty().setIntegrationIdentifier( + key: "branch_id", + value: <BRANCH_IDENTITY_ID>, + ); - await Adapty().updateAttribution(data, source: AdaptyAttributionSource.branch); + await Adapty().updateAttribution(data, source: "branch"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ); ``` ### Firebase ve Google Analytics Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; try { - final builder = AdaptyProfileParametersBuilder() - ..setFirebaseAppInstanceId(appInstanceId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Mixpanel entegrasyonu için SDK yapılandırması](mixpanel#sdk-configuration) sayfasına bakın. ```diff showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setMixpanelUserId(distinctId); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "mixpanel_user_id", + value: distinctId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) sayfasına bakın. ```diff showLineNumbers OneSignal.shared.setSubscriptionObserver((changes) { final playerId = changes.to.userId; if (playerId != null) { - final builder = - AdaptyProfileParametersBuilder() - ..setOneSignalPlayerId(playerId); - // ..setOneSignalSubscriptionId(playerId); try { - Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId, + ); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle error } } }); ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırması](pushwoosh#sdk-configuration) sayfasına bakın. ```diff showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; - final builder = AdaptyProfileParametersBuilder() - ..setPushwooshHWID(hwid); try { - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: hwid, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Observer mode uygulamasını güncelleyin \{#update-observer-mode-implementation\} Paywall'ları işlemlerle nasıl ilişkilendirdiğinizi güncelleyin. Daha önce `variationId`'yi atamak için `setVariationId` metodunu kullanıyordunuz. Artık `variationId`'yi doğrudan yeni `reportTransaction` metoduyla işlemi kaydederken ekleyebilirsiniz. Nihai kod örneği için [Observer mode'da paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode-flutter) sayfasına bakın. :::warning İşlemi `reportTransaction` metoduyla kaydetmeyi unutmayın. Bu adımı atladığınızda Adapty işlemi tanımayacak, access level vermeyecek, analize dahil etmeyecek ve entegrasyonlara göndermeyecektir. Bu adım zorunludur! ::: ```diff showLineNumbers try { - await Adapty().setVariationId("YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID"); + // every time when calling transaction.finish() + await Adapty().reportTransaction( + "YOUR_TRANSACTION_ID", + variationId: "PAYWALL_VARIATION_ID", // optional + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter-sdk-v3 --- --- title: "Adapty Flutter SDK'yı v3.0'a geçirme" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Flutter SDK v3.0'a geçin." --- Adapty SDK v3.0, no-code ve kullanıcı dostu bir paywall oluşturma aracının yeni sürümü olan [Adapty Paywall Builder](adapty-paywall-builder) desteğini sunuyor. Maksimum esnekliği ve zengin tasarım özellikleriyle paywalllarınız çok daha etkili ve kârlı hale gelecek. :::info AdaptyUI kütüphanesinin kullanımdan kaldırıldığını ve artık AdaptySDK'nın bir parçası olarak dahil edildiğini lütfen unutmayın. ::: ## AdaptyUI SDK'yı Kaldırma \{#remove-adaptyui-sdk\} 1. AdaptyUI artık Adapty SDK içinde bir modül haline geldiğinden, `pubspec.yaml` dosyanızdan `adapty_ui_flutter` bağımlılığını kaldırın: ```diff showLineNumbers dependencies: + adapty_flutter: ^3.2.1 - adapty_flutter: ^2.10.3 - adapty_ui_flutter: ^2.1.3 ``` 2. Şu komutu çalıştırın: ```bash showLineNumbers title="Bash" flutter pub get ``` ## Adapty SDK'yı Yapılandırma \{#configure-adapty-sdks\} Daha önce Adapty SDK yapılandırması için `Adapty-Info.plist` ve `AndroidManifest.xml` dosyalarını kullanmanız gerekiyordu. Artık ek dosyalara gerek yok. Bunun yerine, tüm gerekli parametreleri aktivasyon sırasında doğrudan sağlayabilirsiniz. Adapty SDK'yı yalnızca bir kez yapılandırmanız gerekir; bunu genellikle uygulamanızın yaşam döngüsünün başında yapın. ### Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} 1. AdaptyUI SDK import'unu uygulamanızdan aşağıdaki şekilde kaldırın: ```diff showLineNumbers import 'package:adapty_flutter/adapty_flutter.dart'; - import 'package:adapty_ui_flutter/adapty_ui_flutter.dart'; ``` 2. Adapty SDK aktivasyonunu şu şekilde güncelleyin: ```diff showLineNumbers try { - Adapty().activate(); + await Adapty().activate( + configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') + ..withLogLevel(AdaptyLogLevel.debug) + ..withObserverMode(false) + ..withCustomerUserId(null) + ..withIpAddressCollectionDisabled(false) + ..withIdfaCollectionDisabled(false), + ); } catch (e) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ----------------------------------- | -------- | ------------------------------------------------------------ | | **PUBLIC_SDK_KEY** | zorunlu | Adapty'deki uygulama ayarlarınızın **Public SDK key** alanında bulabileceğiniz anahtar: [**App settings**-> **General** sekmesi -> **API keys** alt bölümü](https://app.adapty.io/settings/general) | | **withLogLevel** | isteğe bağlı | Adapty, uygulamanızın işleyişine dair bilgi sunmak için hataları ve diğer önemli verileri kaydeder. Kullanılabilir log seviyeleri şunlardır:<ul><li> error: Yalnızca hatalar kaydedilir.</li><li> warn: Kritik hatalara yol açmayan ancak dikkat edilmesi gereken hatalar ve SDK mesajları kaydedilir.</li><li> info: Hatalar, uyarılar ve çeşitli modüllerin yaşam döngüsünü kaydeden önemli bilgi mesajları kaydedilir.</li><li> verbose: Hata ayıklama sırasında işe yarayabilecek fonksiyon çağrıları, API sorguları gibi ek bilgiler kaydedilir.</li></ul> | | **withObserverMode** | isteğe bağlı | <p>[Observer mode](observer-vs-full-mode) özelliğini kontrol eden bir boolean değer. Satın alma ve abonelik durumunu kendiniz yönetip Adapty'yi yalnızca abonelik etkinliklerini ve analizleri göndermek için kullanıyorsanız etkinleştirin.</p><p>Varsayılan değer `false`'tur.</p><p></p><p>🚧 Observer mode etkinken Adapty SDK hiçbir işlemi kapatmaz, bu nedenle bunu kendiniz yönettiğinizden emin olun.</p> | | **withCustomerUserId** | isteğe bağlı | Sisteminizdeki kullanıcı tanımlayıcısı. Etkinlikleri doğru profile bağlamak için abonelik ve analitik etkinliklerinde gönderilir. Ayrıca [**Profiles and Segments**](https://app.adapty.io/profiles/users) menüsünden `customerUserId` ile müşteri arayabilirsiniz. | | **withIdfaCollectionDisabled** | isteğe bağlı | <p>IDFA toplama ve paylaşımını devre dışı bırakmak için `true` olarak ayarlayın.</p><p>Kullanıcı IP adresi paylaşımı.</p><p>Varsayılan değer `false`'tur.</p><p>IDFA toplama hakkında daha fazla bilgi için [Analytics integration](analytics-integration#disable-collection-of-advertising-identifiers) bölümüne bakın.</p> | | **withIpAddressCollectionDisabled** | isteğe bağlı | <p>Kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `true` olarak ayarlayın.</p><p>Varsayılan değer `false`'tur.</p> | ### Adapty SDK'nın AdaptyUI Modülünü Etkinleştirme \{#activate-adaptyui-module-of-adapty-sdk\} AdaptyUI modülünü yalnızca [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız yapılandırmanız gerekir: ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer: <AdaptyUIObserver Implementation>, ); } catch (e) { // handle the error } ``` AdaptyUI yapılandırmasının isteğe bağlı olduğunu unutmayın; AdaptyUI modülünü config olmadan da etkinleştirebilirsiniz. Ancak config kullanıyorsanız, içindeki tüm parametreler zorunludur. Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------------------ | :------- | :----------------------------------------------------------- | | **memoryStorageTotalCostLimit** | zorunlu | Depolamanın bayt cinsinden toplam maliyet sınırı. | | **memoryStorageCountLimit** | zorunlu | Bellek depolamasının öğe sayısı sınırı. | | **diskStorageSizeLimit** | zorunlu | Diskteki depolama için bayt cinsinden dosya boyutu sınırı. 0 değeri sınır olmadığı anlamına gelir. | --- # End of Documentation _Generated on: 2026-07-24T13:02:34.317Z_ _Successfully processed: 44/44 files_ # IOS - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.320Z Total files: 44 --- # File: sdk-installation-ios --- --- title: "iOS SDK'yı Yükle ve Yapılandır" description: "Abonelik tabanlı uygulamalar için iOS'ta Adapty SDK kurulumuna ilişkin adım adım kılavuz." --- Adapty SDK, mobil uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için zorunludur. - **AdaptyUI**: Bu isteğe bağlı modül, çapraz platform paywalllar kolayca oluşturmak için kullanıcı dostu, kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek bir örnek görmek ister misiniz? Paywall görüntüleme, satın alma yapma ve diğer temel işlevler dahil olmak üzere tam kurulumu gösteren [örnek uygulamalarımıza](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) göz atın. ::: Ayrıca eksiksiz bir uygulama adım adım anlatımı için şu videolara göz atabilirsiniz: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="iOS (SwiftUI)" default> <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/cSChHc8k2zA?si=KhNFhqXccIzYwTcm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> </TabItem> <TabItem value="uikit" label="iOS (UIKit)" default> <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/WEUnlaAjSI0?si=sjXKVVb56tEHDKzJ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> </TabItem> </Tabs> ## Gereksinimler \{#requirements\} SDK teknik olarak çekirdek modül için iOS 13.0+'ı desteklese de, pratikte iOS 15.0+ zorunludur: - Tüm StoreKit 2 özellikleri iOS 15.0+ gerektirir - AdaptyUI modülü yalnızca iOS 15.0+ ile çalışır :::important Xcode 26.4 veya sonraki sürümlerle derleme yaparken Adapty SDK 3.15.7+ gereklidir. ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükle \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-iOS.svg?style=flat&logo=apple)](https://github.com/adaptyteam/AdaptySDK-iOS/releases) Adapty SDK, Swift Package Manager aracılığıyla yüklenir. Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme adımları Xcode sürümüne göre farklılık gösterebileceğinden, gerekirse Xcode belgelerine başvurun. 1. Depo URL'sini girin: ``` https://github.com/adaptyteam/AdaptySDK-iOS.git ``` 2. Sürümü seçin (en son kararlı sürüm önerilir) ve **Add Package** düğmesine tıklayın. 3. **Choose Package Products** penceresinde ihtiyacınız olan modülleri seçin: - **Adapty** (çekirdek modül) - **AdaptyUI** (isteğe bağlı - yalnızca Paywall Builder kullanmayı planlıyorsanız) :::note Not: - SDK 3.x'te [Kids Mode](kids-mode) özelliğini etkinleştirmek için **Adapty** yerine **Adapty_KidsMode** seçin. SDK 4.0 ve sonrasında ise normal modülleri seçin — Kids Mode, `KidsMode` paket özelliği aracılığıyla etkinleştirilir. - Listeden başka herhangi bir paket seçmeyin – bunlara ihtiyacınız olmayacak. ::: 4. Kurulumu tamamlamak için **Add Package** düğmesine tıklayın. 5. **Kurulumu doğrulayın:** Proje gezgininizde **Package Dependencies** altında "Adapty" (ve seçtiyseniz "AdaptyUI") görünmelidir. :::important Adapty iOS SDK 4.0 ön sürümdür. Swift Package Manager, **Up to Next Major Version** (`from:`) kuralıyla beta sürümlerini çözemez; bu nedenle tam sürümü sabitlemeniz gerekir. Xcode'da **Dependency Rule** ayarını **Exact Version** olarak belirleyin ve `4.0.0-beta.2` girin. `Package.swift` dosyasında `.exact("4.0.0-beta.2")` kullanın. Bkz. [Adapty iOS SDK'yı v4'e Taşıma](migration-to-ios-sdk-v4). ::: ## Adapty SDK'nın Adapty modülünü etkinleştirin \{#activate-adapty-module-of-adapty-sdk\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK'nın uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers @main struct YourApp: App { init() { // Configure Adapty SDK let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard Adapty.logLevel = .verbose // recommended for development and the first production release let config = configurationBuilder.build() // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } var body: some Scene { WindowGroup { // Your content view } } } } ``` </TabItem> <TabItem value="swift" label="UIKit" default> ```swift showLineNumbers // In your AppDelegate class: // If you only use an AppDelegate, place the following code in the // application(_:didFinishLaunchingWithOptions:) method. // If you use a SceneDelegate, place the following code in the // scene(_:willConnectTo:options:) method. Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(logLevel: .verbose) // recommended for development and the first production release let config = configurationBuilder.build() try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> :::important Diğer Adapty SDK metotlarını çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıralama için [iOS SDK'da çağrı sırası](ios-sdk-call-order) sayfasına bakın. ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](ios-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız [özel paywalllar için hızlı başlangıç kılavuzuna](ios-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI Modülünü Etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ve [AdaptyUI modülünü kurduysanız](sdk-installation-ios#install-adapty-sdk), AdaptyUI'ı da etkinleştirmeniz gerekir. :::important Kodunuzda, AdaptyUI'ı etkinleştirmeden önce Adapty çekirdek modülünü etkinleştirmeniz gerekir. ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers title="Swift" @main struct YourApp: App { init() { // ...ConfigurationBuilder steps // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: config) try await AdaptyUI.activate() } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } // main body... } } ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift showLineNumbers title="UIKit" // If you only use an AppDelegate, place the following code in the // application(_:didFinishLaunchingWithOptions:) method. // If you use a SceneDelegate, place the following code in the // scene(_:willConnectTo:options:) method. Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(logLevel: .verbose) // recommended for development let config = configurationBuilder.build() try await Adapty.activate(with: config) try await AdaptyUI.activate() } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> :::tip İsteğe bağlı olarak, AdaptyUI'ı etkinleştirirken [paywall'lar için varsayılan önbellekleme ayarlarını geçersiz kılabilirsiniz](#set-up-media-cache-configuration-for-adaptyui). ::: ## İsteğe Bağlı Kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kayıt sistemini kurma \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki günlük seviyeleri mevcuttur: | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Yalnızca hatalar loglanır | | `warn` | Hatalar ve SDK'dan gelen, kritik hatalara yol açmayan ancak dikkat edilmesi gereken mesajlar loglanır | | `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır | | `verbose` | Hata ayıklama sırasında yararlı olabilecek her türlü ek bilgi (fonksiyon çağrıları, API sorguları vb.) loglanır | ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(logLevel: .verbose) // recommended for development ``` #### Günlük sistemi mesajlarını yönlendirin \{#redirect-the-logging-system-messages\} Adapty'nin günlük mesajlarını kendi sisteminize göndermek veya bir dosyaya kaydetmek istiyorsanız `setLogHandler` metodunu kullanın ve özel günlük mantığınızı bu metodun içinde uygulayın. Bu işleyici, mesaj içeriği ve önem derecesini içeren günlük kayıtları alır. ```swift showLineNumbers title="Swift" Adapty.setLogHandler { record in writeToLocalFile("Adapty \(record.level): \(record.message)") } ``` ### Veri politikaları \{#data-policies\} Adapty, siz açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz. Ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IDFA toplama ve paylaşımını devre dışı bırakma \{#disable-idfa-collection-and-sharing\} Adapty modülünü etkinleştirirken IDFA toplama ve paylaşımını devre dışı bırakmak için `idfaCollectionDisabled` değerini `true` olarak ayarlayın. App Store İnceleme Kuralları'na uymak veya IDFA uygulamanız için gerekli olmadığında App Tracking Transparency istemini tetiklemekten kaçınmak için bu parametreyi kullanın. Varsayılan değer `false` şeklindedir. IDFA toplama hakkında daha fazla bilgi için [Analytics entegrasyonu](analytics-integration#disable-collection-of-advertising-identifiers) bölümüne bakın. ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(idfaCollectionDisabled: true) ``` #### IP toplama ve paylaşımını devre dışı bırakma \{#disable-ip-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` parametresini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; kullanıcı gizliliğini artırmak, bölgesel veri koruma yönetmeliklerine (GDPR veya CCPA gibi) uymak ya da uygulamanızda IP tabanlı özelliklere ihtiyaç duyulmadığında gereksiz veri toplamayı azaltmak için kullanabilirsiniz. ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(ipAddressCollectionDisabled: true) ``` #### AdaptyUI'da paywall'lar için medya önbellek yapılandırması \{#media-cache-configuration-for-paywalls-in-adaptyui\} AdaptyUI yapılandırmasının isteğe bağlı olduğunu unutmayın. AdaptyUI modülünü yapılandırma olmadan da etkinleştirebilirsiniz. Ancak yapılandırmayı kullanıyorsanız tüm parametreler zorunludur. ```swift showLineNumbers title="Swift" // Configure AdaptyUI let adaptyUIConfiguration = AdaptyUI.Configuration( mediaCacheConfiguration: .init( memoryStorageTotalCostLimit: 100 * 1024 * 1024, memoryStorageCountLimit: .max, diskStorageSizeLimit: 100 * 1024 * 1024 ) ) // Activate AdaptyUI AdaptyUI.activate(configuration: adaptyUIConfiguration) ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :-------------------------- | :--------- | :----------------------------------------------------------- | | memoryStorageTotalCostLimit | zorunlu | Depolama alanının bayt cinsinden toplam maliyet sınırı. | | memoryStorageCountLimit | zorunlu | Bellek depolama alanının öğe sayısı sınırı. | | diskStorageSizeLimit | zorunlu | Depolama alanının diskteki dosya boyutu sınırı (bayt cinsinden). 0, sınır olmadığı anlamına gelir. | ### İşlem Tamamlama Davranışı \{#transaction-finishing-behavior\} :::info Bu özellik SDK 3.12.0 sürümünden itibaren kullanılabilir. ::: Adapty, varsayılan olarak işlemleri başarılı doğrulamanın ardından otomatik olarak tamamlar. Ancak gelişmiş işlem doğrulamasına ihtiyaç duyuyorsanız (sunucu taraflı makbuz doğrulama, sahtekarlık tespiti veya özel iş mantığı gibi), SDK'yı manuel işlem tamamlama modunda çalışacak şekilde yapılandırabilirsiniz. ```swift showLineNumbers title="Swift" let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(transactionsFinishBehavior: .manual) // .auto varsayılandır ``` İşlemlerin nasıl tamamlanacağına dair daha fazla ayrıntı için [kılavuza](ios-transaction-management) bakın. ### Yedekten geri yüklemede verileri temizle \{#clear-data-on-backup-restore\} `clearDataOnBackup` değeri `true` olarak ayarlandığında, SDK uygulamanın bir iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywaller dahil yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(clearDataOnBackup: true) // default – false ``` ## Sorun Giderme \{#troubleshooting\} #### Tuist ile Swift 6 eşzamanlılık hatası \{#swift-6-concurrency-error-with-tuist\} [Tuist](https://tuist.dev/) ile derleme yaparken Swift 6 strict concurrency derleme hatalarıyla karşılaşabilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içinde `@Sendable` özellik uyumsuzlukları veya benzer modüller arası Sendability hataları yer alır. Bu durum, Tuist'in SPM paketlerinden Xcode projeleri oluşturmasına ancak `swift-tools-version: 6.0` ayarını korumamasına bağlıdır. Sonuç olarak bazı Adapty hedefleri (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`) Swift 5 kurallarıyla derlenirken diğerleri Swift 6 kullanır ve bu durum modüller arası `@Sendable` uyuşmazlıklarına yol açar. **Düzeltme**: Adapty SDK **3.15.5** veya sonraki bir sürüme yükseltin; bu sürüm, karışık Swift dil sürümlerinden bağımsız olarak sorunu çözer. **Geçici çözüm**: Yükseltme yapamıyorsanız Tuist yapılandırmanızda üç Adapty hedefinin tamamı için Swift 6'yı açıkça belirtin: ```swift showLineNumbers targetSettings: [ "Adapty": .init().swiftVersion("6"), "AdaptyUI": .init().swiftVersion("6"), "AdaptyUIBuilder": .init().swiftVersion("6"), ] ``` --- # File: ios-quickstart-paywalls --- --- title: "iOS SDK'da Flow Builder ile satın almaları etkinleştirin" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmeye yönelik hızlı başlangıç kılavuzu." --- Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – ürünleri kullanıcılara sunan, no-code Flow Builder ile oluşturulan ekran dizileri. SDK bunları `getFlow` ile alır. Kullanıcı arayüzünü kendi kodunuzla oluşturmayı tercih ederseniz, bunun yerine paywall kullanın — bkz. [Paywallları manuel olarak uygulama](ios-quickstart-manual). - [**Placement'lar**](placements) – uygulamanızda flow'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'si ile talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek çok kolay olur. Adapty, uygulamanızda satın alımları etkinleştirmeniz için üç yol sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | [No-code builder'da eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm karmaşık satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda halleder. | | Elle oluşturulan paywalllar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine Adapty'den alırsınız. [Rehbere](ios-quickstart-manual) göz atın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı kısıtlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl uygulanacağını göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, bkz. [Paywall'ları manuel olarak uygulama](ios-quickstart-manual). ::: Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Görüntüleyin, satın almaları Adapty sizin için yönetecektir**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butona tıkladığında bağlantılar açın veya flow'u kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Adapty Kontrol Paneli'nde [uygulamanızı App Store'a bağlayın](initial_ios). 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ürünleri ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'u ekleyin](create-placement). 5. Uygulama kodunuzda [Adapty SDK'yı yükleyip etkinleştirin](sdk-installation-ios). Bu kılavuz Adapty iOS SDK v4 API'lerini kullanmaktadır. ## 1. Flow'u edinin \{#1-get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testi](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturulan bir flow'u edinmek için şunları yapmanız gerekir: 1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın ve bir görünüm yapılandırması içerip içermediğini kontrol edin. 2. `getFlowConfiguration` metodunu kullanarak görünüm yapılandırmasını edinin. Bu yapılandırma, flow'u görüntülemek için gereken UI öğelerini ve stil bilgilerini içerir. ```swift func loadFlow() async { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow'un bir görünüm yapılandırması yok") return } flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) } ``` ## 2. Flow'u göster \{#display-the-flow\} Artık flow konfigürasyonuna sahipsiniz; flow'u göstermek için birkaç satır kod eklemeniz yeterli. <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> SwiftUI'da flow'u gösterirken aynı zamanda olayları da ele almanız gerekir. `didFinishPurchase`, `didFailPurchase`, `didFinishRestore`, `didFailRestore` ve `didReceiveError` zorunludur. Test sırasında bu olayları kaydetmek için aşağıdaki kod parçacığını doğrudan kopyalayabilirsiniz. :::tip Flow, başarılı bir satın alma işleminin ardından otomatik olarak kapanmaz. `didFinishPurchase` içinde, flow'u kapatmak için sunum bağlantınızı `false` olarak ayarlayın ya da flow'un sonraki ekranlarına devam etmesi için hiçbir şey yapmayın. ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didFinishPurchase: { product, purchaseResult in print("Purchase finished successfully") flowPresented = false // or do nothing to let the flow continue }, didFailPurchase: { product, error in print("Purchase failed: \(error)") }, didFinishRestore: { profile in print("Restore finished successfully") }, didFailRestore: { error in print("Restore failed: \(error)") }, didReceiveError: { error in flowPresented = false print("Flow error: \(error)") } ) ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift func presentFlow(with config: AdaptyUI.FlowConfiguration) { let flowController = try AdaptyUI.flowController( with: config, delegate: self ) present(flowController, animated: true) } ``` `AdaptyFlowControllerDelegate`'i olayları ele almak için uygulayın. En azından varsayılan uygulaması olmayan dört metodu implemente edin. Dikkat: controller başarılı bir satın almanın ardından kendini kapatmaz — `didFinishPurchase` içinde kapatın ya da flow'un sonraki ekranlarına devam etmesine izin vermek için hiçbir şey yapmayın: ```swift extension YourViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didFinishPurchase product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { if !purchaseResult.isPurchaseCancelled { controller.dismiss(animated: true) // or do nothing to let the flow continue } } func flowController(_ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError) { print("Purchase failed: \(error)") } func flowController(_ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile) { print("Restore finished successfully") } func flowController(_ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError) { print("Restore failed: \(error)") } } ``` </TabItem> </Tabs> :::info Bir flow'un nasıl görüntüleneceğine dair daha fazla ayrıntı için [rehberimize](ios-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#handle-button-actions\} Kullanıcılar butona tıkladığında, iOS SDK satın alma işlemlerini, geri yüklemeleri, flow'u kapatmayı ve bağlantı açmayı otomatik olarak yönetir. Ancak bazı butonların özel veya önceden tanımlanmış kimlikleri vardır ve kodunuzda eylemlerin yönetilmesini gerektirir. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, kapat butonunu şu şekilde yönetebilirsiniz. UIKit'te, `.close` tetiklendiğinde SDK controller'ı otomatik olarak kapatır — yalnızca özel bir davranış istiyorsanız geçersiz kılın. SwiftUI'da ise `isPresented` binding'inizi kendiniz `false` olarak ayarlamanız gerekir. :::tip Buton [aksiyonlarını](handle-paywall-actions) ve [olayları](ios-handling-events) nasıl yöneteceğinize dair kılavuzlarımızı okuyun. ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false // dismiss the flow when the user taps close default: break } }, didFinishPurchase: { product, purchaseResult in flowPresented = false }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift extension YourViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didPerform action: AdaptyUI.Action) { switch action { case .close: controller.dismiss(animated: true) // varsayılan davranış — yalnızca gerektiğinde geçersiz kılın default: break } } } ``` </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Flow'unuz uygulamada görüntülenmeye hazır. Bir test satın alma işlemini tamamlayabildiğinizden emin olmak için [satın almalarınızı sandbox modunda test edin](test-purchases-in-sandbox). Şimdi, flow'u veya ücretli özelliklere erişimi doğru kullanıcılara sunduğunuzdan emin olmak için [kullanıcıların access level'ını kontrol etmeniz](ios-check-subscription-status) gerekiyor. ## Tam örnek \{#full-example\} Bu rehberdeki tüm adımların uygulamanıza birlikte nasıl entegre edileceği aşağıda gösterilmektedir. <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> ```swift struct ContentView: View { @State private var flowPresented = false @State private var flowConfiguration: AdaptyUI.FlowConfiguration? @State private var isLoading = false @State private var hasInitialized = false var body: some View { VStack { if isLoading { ProgressView("Loading...") } else { Text("Your App Content") } } .task { guard !hasInitialized else { return } await initializeFlow() hasInitialized = true } .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false default: break } }, didFinishPurchase: { product, purchaseResult in print("Purchase finished successfully") flowPresented = false // or do nothing to let the flow continue }, didFailPurchase: { product, error in print("Purchase failed: \(error)") }, didFinishRestore: { profile in print("Restore finished successfully") }, didFailRestore: { error in print("Restore failed: \(error)") }, didReceiveError: { error in print("Flow error: \(error)") flowPresented = false } ) } private func initializeFlow() async { isLoading = true defer { isLoading = false } await loadFlow() flowPresented = true } private func loadFlow() async { do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow doesn't have a view configuration") return } flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) } catch { print("Failed to load: \(error)") } } } ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift class ViewController: UIViewController { private var flowConfiguration: AdaptyUI.FlowConfiguration? override func viewDidLoad() { super.viewDidLoad() Task { await initializeFlow() } } private func initializeFlow() async { do { flowConfiguration = try await loadFlow() if let flowConfiguration { await MainActor.run { presentFlow(with: flowConfiguration) } } } catch { print("Error initializing: \(error)") } } private func loadFlow() async throws -> AdaptyUI.FlowConfiguration? { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow doesn't have a view configuration") return nil } return try await AdaptyUI.getFlowConfiguration(forFlow: flow) } private func presentFlow(with config: AdaptyUI.FlowConfiguration) { guard let flowController = try? AdaptyUI.flowController( with: config, delegate: self ) else { return } present(flowController, animated: true) } } extension ViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didFinishPurchase product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { if !purchaseResult.isPurchaseCancelled { controller.dismiss(animated: true) // or do nothing to let the flow continue } } func flowController(_ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError) { print("Purchase failed for \(product.vendorProductId): \(error)") guard error.adaptyErrorCode != .paymentCancelled else { return } let message = switch error.adaptyErrorCode { case .paymentNotAllowed: "Purchases are not allowed on this device." default: "Purchase failed. Please try again." } let alert = UIAlertController(title: "Purchase Error", message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } func flowController(_ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile) { print("Restore finished successfully") controller.dismiss(animated: true) } func flowController(_ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError) { print("Restore failed: \(error)") } func flowController(_ controller: AdaptyFlowController, didReceiveError error: AdaptyUIError) { print("Flow error: \(error)") controller.dismiss(animated: true) } } ``` </TabItem> </Tabs> --- # File: ios-check-subscription-status --- --- title: "iOS SDK'da abonelik durumunu kontrol etme" description: "Adapty ile iOS uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir. Bu makale, kullanıcılara paywall gösterip göstermeyeceğinizi veya ücretli özelliklere erişim verip vermeyeceğinizi belirlemek amacıyla profil durumuna nasıl erişeceğinizi gösteriyor. ## Abonelik durumunu alma \{#get-subscription-status\} Kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken, profillerindeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verisine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) ya da zorla güncelleme yapmak istediğinizde `getProfile` çağırın. - Abonelik durumu her değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** etkinleştirin. :::important Adapty'de varsayılan olarak `premium` access level zaten mevcuttur. Birden fazla access level ayarlamanıza gerek yoksa `premium` değerini doğrudan kullanabilirsiniz. ::: ### Profil alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> </Tabs> ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak istiyorsanız: 1. İstediğiniz bir türde `AdaptyDelegate` protokolünü uygulayın ve `didLoadLatestProfile` metodunu implemente edin; Adapty, kullanıcının abonelik durumu her değiştiğinde bu metodu otomatik olarak çağırır. Aşağıdaki örnekte abonelik iş akışlarını ve kullanıcı profilini yönetmek için bir `SubscriptionManager` türü kullanıyoruz. Bu tür bir bağımlılık olarak enjekte edilebilir, UIKit uygulamasında singleton olarak kurulabilir ya da uygulamanın ana struct'ından SwiftUI ortamına eklenebilir. 2. Bu metot çağrıldığında güncellenen profil verisini saklayın; böylece ek ağ isteği yapmadan uygulama genelinde kullanabilirsiniz. ```swift class SubscriptionManager: AdaptyDelegate { nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { let hasAccess = profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false // Update UI, unlock content, etc. } } // Set delegate after Adapty activation Adapty.delegate = subscriptionManager ``` :::note Adapty, uygulamanız başladığında `didLoadLatestProfile` metodunu otomatik olarak çağırır ve cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verisini sağlar. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim verme konusunda anlık kararlar almanız gerektiğinde, kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girerken veya belirli içerikleri görüntülemeden önce gibi senaryolarda kullanışlıdır. <Tabs> <TabItem value="swiftui" label="SwiftUI" default> ```swift private func checkAccessLevel() async -> Bool { do { let profile = try await Adapty.getProfile() return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false } catch { print("Error checking access level: \(error)") return false } } // In your initialization logic: let hasAccess = await checkAccessLevel() if !hasAccess { paywallPresented = true // Show paywall if no access } ``` </TabItem> <TabItem value="uikit" label="UIKit"> ```swift private func checkAccessLevel() async throws -> Bool { let profile = try await Adapty.getProfile() return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false } // In your initialization logic: let hasAccess = try await checkAccessLevel() if !hasAccess { presentPaywall(with: paywallConfiguration) } ``` </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, mevcut kimlik doğrulama sisteminizle ve ücretli erişim paylaşım izinleriyle uyumlu olduğundan emin olmak için [kullanıcı profilleriyle nasıl çalışacağınızı](ios-quickstart-identify) öğrenin. Kendi kimlik doğrulama sisteminiz yoksa bu hiç sorun değil; Adapty kullanıcıları sizin yerinize yönetir. Yine de Adapty'nin anonim kullanıcılarla nasıl çalıştığını öğrenmek için [kılavuzu](ios-quickstart-identify) okuyabilirsiniz. --- # File: ios-quickstart-identify --- --- title: "iOS SDK'da kullanıcıları tanımlama" description: "Uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa size yöneliktir. Burada, Adapty'deki kullanıcı profillerinin mevcut kimlik doğrulama sisteminizle uyumlu çalışmasını nasıl sağlayacağınızı öğreneceksiniz. ::: Kullanıcıların satın alımlarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız arka uç kimlik doğrulaması kullanmıyor ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanız arka uç kimlik doğrulamasına sahipse (veya ileride sahip olacaksa), [tanımlanmış kullanıcılar bölümüne](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmadan)** veya tanımlanmış **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi dahili kimlik doğrulama sisteminizle çapraz referanslamak için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |----------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profiller | Oturumlar ve cihazlar genelinde aynı profil | | **Veri sürekliliği** | Anonim kullanıcıların verileri uygulama yüklemesine bağlıdır | Tanımlanmış kullanıcıların verileri uygulama yüklemeleri arasında korunur | ## Anonim kullanıcılar \{#anonymous-users\} Arka uç kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı işlemenize gerek yoktur**: 1. SDK, uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profili ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **aktivasyonda yeni bir anonim profil oluşturur**. 4. Kullanıcı uygulamanızda daha önce satın alma yapmışsa, varsayılan olarak satın alımları SDK aktivasyonunda App Store'dan otomatik olarak senkronize edilir. :::note Yedekten geri yükleme, yeniden yüklemeden farklı davranır. Varsayılan olarak, bir kullanıcı yedekten geri yükleme yaptığında SDK önbelleğe alınan verileri korur ve yeni bir profil oluşturmaz. Bu davranışı `clearDataOnBackup` ayarını kullanarak yapılandırabilirsiniz. [Daha fazla bilgi edinin](sdk-installation-ios#clear-data-on-backup-restore). ::: Anonim kullanıcılarda her yüklemede yeni profiller oluşturulacaktır, ancak bu bir sorun değildir; çünkü Adapty analitiğinde [yeni yükleme olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için yüklemeleri **cihaz ID'lerine** göre saymanız gerekir. Bu durumda, yeniden yüklemeler de dahil olmak üzere bir cihazdaki her uygulama yüklemesi bir yükleme olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Kullanıcıları uygulamada tanımlamak için iki seçeneğiniz vardır: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğruladıklarında `identify()` metodunu bir customer user ID ile çağırın. - [**SDK aktivasyonu sırasında:**](#during-the-sdk-activation) Uygulama başlatıldığında zaten depolanmış bir customer user ID'niz varsa, bunu `activate()` çağrısında gönderin. :::important Varsayılan olarak, Adapty başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; dolayısıyla her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Ayrıntılar için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin uygulamanıza giriş yaptıktan veya kaydolduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty onu otomatik olarak mevcut profile bağlar. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır. Parametreye sabit bir değer atarsanız, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir. ::: `identify` metodunu her zaman `await` ile çağırın ve ardından diğer SDK metodlarını kullanın. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar veya anonim profil üzerinde işlem yapar. Bkz. [iOS SDK'da çağrı sırası](ios-sdk-call-order). <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Her kullanıcı için benzersiz olmalıdır } catch { // hatayı işleyin } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // Kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır Adapty.identify("YOUR_USER_ID") { error in if let error { // hatayı işleyin } } ``` </TabItem> </Tabs> ### SDK aktivasyonu sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` metodunu ayrıca çağırmak yerine bunu `activate` metodunda gönderebilirsiniz. Bir customer user ID bilmenize rağmen bunu yalnızca aktivasyon sonrasında ayarlarsanız, aktivasyonda Adapty yeni bir anonim profil oluşturacak ve siz `identify` metodunu çağırdıktan sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız bir ID) veya yeni bir tane geçirebilirsiniz. Yeni bir tane geçerseniz, aktivasyonda oluşturulan yeni profil otomatik olarak customer user ID'ye bağlanacaktır. :::note Varsayılan olarak, anonim profil oluşturma analitik kontrol panellerini etkilemez; çünkü yüklemeler cihaz ID'lerine göre sayılır. Bir cihaz ID'si, bir cihazdaki mağazadan yapılan tek bir uygulama yüklemesini temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, ilk mi yoksa tekrarlanan bir yükleme mi olduğuna ya da mevcut bir customer user ID'nin kullanılıp kullanılmadığına bağlı değildir. Profil oluşturma (SDK aktivasyonunda veya çıkış yapılmasında), oturum açma veya uygulamayı yeniden yüklemeden güncelleme, ek yükleme olayları oluşturmaz. Yüklemeleri cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // Place in the app main struct for SwiftUI or in AppDelegate for UIKit let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // Place in the app main struct for SwiftUI or in AppDelegate for UIKit let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` </TabItem> </Tabs> ### Kullanıcı oturumunu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir butonunuz varsa, `logout` metodunu kullanın. :::important Kullanıcının oturumunu kapatmak, o kullanıcı için yeni bir anonim profil oluşturur. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.logout() } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.logout { error in if error == nil { // successful logout } } ``` </TabItem> </Tabs> :::info Kullanıcıları tekrar uygulamaya giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın almaya izin verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıklarında erişimlerini kaybetmeyeceklerinden emin olmanız gerekir: 1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil ID'sine bağlar. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin satın alma kayıt olmadan önce yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), profil geçişinin ardından gerçek access level'ı almanız gerekir. Tanımlamanın hemen ardından [`getProfile`](ios-check-subscription-status) metodunu çağırabilir veya verinin otomatik olarak senkronize olması için [profil güncellemelerini dinleyebilirsiniz](ios-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanıza uygulama içi ödeme mantığını başarıyla uyguladınız! Uygulamanızın monetizasyonunda başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](test-purchases-in-sandbox): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboardings**](ios-onboardings): Kullanıcıları onboarding'lerle etkileşime geçirin ve elde tutma oranını artırın - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analitik hizmetleriyle entegre edin - [**Özel profil öznitelikleri ayarlama**](setting-user-attributes): Kullanıcı profillerine özel öznitelikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi iOS uygulamanıza entegre edin" description: "Adapty SDK'sını iOS uygulamanıza uçtan uca entegre etmek için AI kodlama aracınızla adapty-sdk-integration becerisini kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu özellik beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, her aşamada yapay zeka aracınıza doğru dokümanları sunan [adım adım entegrasyon kılavuzunu](adapty-cursor) takip edin. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor --- --- title: "Adapty'yi iOS uygulamanıza AI yardımıyla entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi iOS uygulamanıza adım adım entegre etme kılavuzu." --- Bu rehber, bir yapay zeka kodlama aracı yardımıyla Adapty'yi iOS uygulamanıza adım adım entegre etmenizi sağlar — doğru Adapty dokümanlarını doğru sırayla besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı yapılandırmalar gerektiriyor. Bunu etkileşimli bir LLM becerisiyle ya da kontrol paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'ları, paywall'ları ve placement'ları doğrudan kurmasını sağlar — her adım için kontrol panelini açmanıza gerek kalmaz. Yalnızca [mağazanızı bağlamanız](integrate-payments) gerekir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra agent'ınızda `/adapty-cli` komutunu çalıştırın. Mağazanızı bağlamak için kontrol panelini açmanız gereken anlar dahil her adımda sizi yönlendirecektir. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için bulamaz — bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazanızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin. Satın almaların çalışması için bu zorunludur. [App Store'u bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin ve **API keys** bölümünü bulun. Kodda bu, `Adapty.activate("YOUR_PUBLIC_SDK_KEY")` çağrısına geçirdiğiniz dizedir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere koddan doğrudan başvurmazsınız — Adapty bunları flow'lar veya paywall'lar aracılığıyla iletir. [Ürün ekleyin](quickstart-products) 4. **Bir flow veya paywall ve bir placement oluşturun**: Adapty Kontrol Paneli'nde bir flow (ya da kullanıcı arayüzünü kendiniz oluşturacaksanız bir paywall) oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `Adapty.getFlow("YOUR_PLACEMENT_ID")` fonksiyonuna geçirdiğiniz string değerdir. [Flow oluşturun](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde **Products** sayfasındaki her ürün için yapılandırın. Kodda `profile.accessLevels["premium"]` içinde kontrol edilen dizedir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne göre farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kod yazmaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Bu beşini tamamladığınızda kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodu üretebilir. ::: ### Hazır olduğunuzda yapılandırın \{#set-up-when-ready\} Kodlamaya başlamak için bunlar zorunlu değil, ancak entegrasyonunuz olgunlaştıkça ihtiyacınız olacak: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek flow'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getFlow` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## Adapty dokümanlarını LLM'inize gönderin \{#feed-adapty-docs-to-your-llm\} ### Context7 kullanın (önerilen) \{#use-context7-recommended\} [Context7](https://context7.com), LLM'inize güncel Adapty dokümantasyonuna doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, ne sorduğunuza göre doğru dokümanları otomatik olarak getirir — manuel URL yapıştırmaya gerek kalmaz. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurmak için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra prompt'larınızda Adapty kütüphanesine başvurun: ``` Use the adaptyteam/adapty-docs library to look up how to install the iOS SDK ``` :::warning Context7 doküman bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalışması için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Herhangi bir Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** düğmesine tıklayın. Örnek: [adapty-cursor.md](https://adapty.io/docs/tr/adapty-cursor.md). Aşağıdaki [uygulama adımlarının](#implementation-walkthrough) her biri, yapıştırabileceğiniz `.md` bağlantılarıyla bir "LLM'inize gönderin" bloğu içerir. Aynı anda daha fazla dokümantasyon için aşağıdaki [dizin dosyaları ve platforma özgü alt kümeler](#plain-text-doc-index-files) bölümüne bakın. ## Uygulama adımları \{#implementation-walkthrough\} Bu kılavuzun geri kalanı, uygulama sırasına göre Adapty entegrasyonunu ele alır. Her aşamada LLM'inize gönderilecek dokümanlar, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar yer alır. ### Entegrasyonunuzu planlayın \{#plan-your-integration\} Koda atlamadan önce LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor veya Claude Code'un plan modu gibi), kod yazmadan önce LLM'in hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bu modu kullanın. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, hangi kılavuzları takip etmesi gerektiğini etkiler: - [**Adapty Flow Builder**](adapty-flow-builder): Flow'ları Adapty'nin no-code builder'ında oluşturursunuz; SDK bunları otomatik olarak render eder. - [**Manuel oluşturulan paywalllar**](ios-quickstart-manual): Kendi paywall arayüzünüzü kodla inşa edersiniz, ancak ürünleri getirmek ve satın almaları yönetmek için Adapty'yi kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](ios-quickstart-paywalls) okuyun. ### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\} Adapty SDK paketini Xcode'da Swift Package Manager aracılığıyla yükleyin ve Public SDK anahtarınızla etkinleştirin. Bu temeldir — bunu yapmadan hiçbir şey çalışmaz. **Kılavuz:** [Adapty SDK'yı yükleyin ve yapılandırın](sdk-installation-ios) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-ios.md ``` :::tip[Kontrol noktası] - **Beklenen:** Uygulama derlenir ve çalışır. Xcode konsolu Adapty aktivasyon logunu gösterir. - **Dikkat:** "Public API key is missing" hatası → placeholder'ı App settings'deki gerçek anahtarınızla değiştirdiğinizi doğrulayın. ::: ### Flow veya paywall gösterme ve satın alma işlemlerini yönetme \{#show-flows-or-paywalls-and-handle-purchases\} Placement ID'ye göre bir flow veya paywall getirin, görüntüleyin ve satın alma olaylarını yönetin. İhtiyacınız olan kılavuzlar, satın alma işlemlerini nasıl yönettiğinize bağlıdır. Her satın almayı ilerlerken sandbox'ta test edin — sona bırakmayın. Kurulum talimatları için [Sandbox'ta satın alma testi](test-purchases-in-sandbox) bölümüne bakın. <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Flow Builder" default> **Kılavuzlar:** - [Flow Builder ile satın almaları etkinleştirin (hızlı başlangıç)](ios-quickstart-paywalls) - [Flow'ları ve yapılandırmalarını alın](get-pb-paywalls) - [Flow'ları görüntüleyin](ios-present-paywalls) - [Flow olaylarını yönetin](ios-handling-events) - [Buton eylemlerine yanıt verin](handle-paywall-actions) Bu metni LLM'inize gönderin: ``` Kod yazmadan önce şu Adapty dokümanlarını okuyun: - https://adapty.io/docs/tr/ios-quickstart-paywalls.md - https://adapty.io/docs/tr/get-pb-paywalls.md - https://adapty.io/docs/tr/ios-present-paywalls.md - https://adapty.io/docs/tr/ios-handling-events.md - https://adapty.io/docs/tr/handle-paywall-actions.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Flow, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikler. - **Dikkat:** Boş flow veya `getFlow` hatası → placement ID'nin kontrol panelindekiyle birebir eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manuel paywalllar"> **Kılavuzlar:** - [Özel paywall'ınızda satın almaları etkinleştirme (hızlı başlangıç)](ios-quickstart-manual) - [Paywall ve ürünleri getirme](fetch-paywalls-and-products) - [Remote config ile tasarlanmış paywall'ı gösterme](present-remote-config-paywalls) - [Satın alma yapma](making-purchases) - [Satın almaları geri yükleme](restore-purchase) Bu bir dokümantasyon çeviri görevi değil — bu, bir kullanıcının LLM'sine göndermesi için hazırlanmış bir mesajdır. Çevirilecek MDX dokümantasyonu içermediğinden herhangi bir çıktı üretemem. Lütfen çevirmemi istediğiniz MDX dokümantasyon içeriğini paylaşın. :::tip[Kontrol Noktası] - **Beklenen:** Özel paywall'ınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikliyor. - **Dikkat:** Boş ürünler dizisi → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitlesi olduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Observer mode"> **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode) :::tip[Checkpoint] - **Beklenen:** Mevcut satın alma akışınızı kullanarak sandbox ortamında yapılan bir satın alma işleminin ardından, işlem Adapty kontrol panelindeki **Event Feed** bölümünde görünür. - **Dikkat:** Hiçbir olay görünmüyorsa → işlemleri Adapty'ye raporladığınızı ve App Store Server Notifications'ın yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol edin \{#check-subscription-status\} Satın alma işleminin ardından premium içeriği kısıtlamak için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin. **Kılavuz:** [Abonelik durumunu kontrol edin](ios-check-subscription-status) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/ios-check-subscription-status.md ``` :::tip[Kontrol noktası] - **Beklenen:** Bir sandbox satın almasının ardından `profile.accessLevels["premium"]?.isActive` değeri `true` döner. - **Dikkat:** Satın alma sonrası boş `accessLevels` → ürüne kontrol panelinde bir access level atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Satın almaların cihazlar arasında saklanabilmesi için uygulama kullanıcı hesaplarınızı Adapty profilleriyle ilişkilendirin. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](ios-quickstart-identify) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/ios-quickstart-identify.md ``` :::tip[Kontrol noktası] - **Beklenen:** `Adapty.identify("your-user-id")` çağrısının ardından kontrol paneli **Profiles** bölümü özel kullanıcı ID'nizi gösterir. - **Dikkat:** Anonim profil attribution sorunlarından kaçınmak için `identify`'ı aktivasyondan sonra ama paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlanın \{#prepare-for-release\} Entegrasyonunuz sandbox'ta çalışır hale geldiğinde, her şeyin üretime hazır olduğundan emin olmak için yayın kontrol listesini adım adım geçin. **Kılavuz:** [Yayın kontrol listesi](release-checklist) LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Kontrol noktası] - **Beklenen:** Tüm kontrol listesi maddeleri onaylandı: mağaza bağlantısı, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** App Store Server Notifications eksik → bunları **App settings → iOS SDK** bölümünden yapılandırın; aksi halde olaylar kontrol panelinde görünmez. ::: ## Düz metin doküman dizin dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam vermeniz gerekirse, tüm Adapty dokümantasyonunu listeleyen veya birleştiren dizin dosyaları sunuyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): `.md` bağlantılarıyla tüm sayfaları listeler. Web sitelerini LLM'lere erişilebilir kılmaya yönelik [gelişmekte olan bir standart](https://llmstxt.org/). Bazı AI agent'lar (örn. ChatGPT) için `llms.txt` dosyasını indirip sohbete yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hali. Çok büyüktür — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - iOS'a özgü [`ios-llms.txt`](https://adapty.io/docs/tr/ios-llms.txt) ve [`ios-llms-full.txt`](https://adapty.io/docs/tr/ios-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: get-pb-paywalls --- --- title: "Flow ve paywall'ları alma - iOS" description: "iOS uygulamanızda Adapty'den flow ve paywall'ları getirme." --- <SDKv4> <MethodPromo method="getFlow" /> [flow veya Paywall Builder paywall'unuzu tasarladıktan](adapty-paywall-builder) sonra bunu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'u ve görünüm yapılandırmasını almaktır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek dünya örneği görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma işlemleri ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Başlamadan önce</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-ios) kurun. </details> ## Flow/paywall getirme \{#fetch-flowpaywall\} Flow Builder veya Paywall Builder ile bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda nasıl render edileceği konusunda endişelenmenize gerek yok. Bu tür bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. Bununla birlikte, placement aracılığıyla ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir. Flow veya paywall'ı ve onun [görüntüleme yapılandırmasını](get-pb-paywalls#fetch-the-view-configuration) mümkün olduğunca erken çekin — ideal olarak göstermeden çok önce. Görüntüleme yapılandırmasını çeker çekmez, SDK arka planda görsellerini indirmeye ve önbelleğe almaya başlar. Ne kadar erken çekerseniz, bu indirmelerin tamamlanması için o kadar fazla zaman olur. Flow veya paywall'ı gösterdiğinizde, yapılandırma ve görseller zaten önbellekte hazır olabilir. Bir flow veya paywall almak için `getFlow` metodunu kullanın: <Tabs> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") // istenen flow/paywall } catch { // hatayı işle } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // istenen flow/paywall case let .failure(error): // hatayı işle } } ``` </TabItem> </Tabs> Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son veriye ulaşamayabilir, ama internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir; dolayısıyla ağ isteklerini azaltmak için oturum boyunca güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywalllarınızın her zaman en güncel halini almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Arka planda işlem farklı isteklerden oluşabileceğinden, nadir durumlarda bu metodun `loadTimeout` ile belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, remote config'ler ve flow'un bir görünüm yapılandırması içerip içermediğini belirten `hasViewConfiguration` bayrağını barındıran bir `AdaptyFlow` nesnesi. Ürünleri ön yükleme, özel kullanıcı arayüzü veya programatik kontroller için getirmek üzere `getPaywallProducts(flow:)` çağırın. | ## Görünüm yapılandırmasını getir \{#fetch-the-view-configuration\} Flow veya paywallı getirdikten sonra, `flow.hasViewConfiguration` ile görünüm yapılandırması içerip içermediğini kontrol edin. Bu bayrak, placement'ın Adapty Kontrol Paneli'nde nasıl tasarlandığını ayırt eder: - **`true`** — placement, **Flow Builder** (bir flow) veya **Paywall Builder** (bir paywall) kullanılarak tasarlanmış. Adapty arayüzü sizin için render eder. Görünüm yapılandırmasını getirmek ve [flow veya paywallı sunmak](ios-present-paywalls) için aşağıdaki adımlarla devam edin. - **`false`** — placement, Builder arayüzü olmayan özel bir paywall. `getFlowConfiguration` yöntemini kullanarak görünüm yapılandırmasını yükleyin. ```swift showLineNumbers guard flow.hasViewConfiguration else { // handle as remote config paywall return } let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) ``` Parametreler: | Parametre | Varlık | Açıklama | | :----------------------- | :------------- | :---------- | | **forFlow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `nil`</p> | [Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. `-` ile ayrılmış bir veya iki alt etiket içeren dil kodu olarak beklenir (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes). | | **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür. Nadir durumlarda bu metod, arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir. | | **products** | isteğe bağlı | Ekranda ürünlerin gösterim zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **systemRequestsHandler** | isteğe bağlı | Flow aksiyonları tarafından tetiklenen sistem izni ve inceleme isteklerini yöneten, `AdaptySystemRequestsHandler` protokolüne uyan bir nesne. Yalnızca flow'unuz bu tür aksiyonlar içeriyorsa gereklidir. | | **assetsResolver** | isteğe bağlı | Flow/paywall içindeki resim ve videoları geçersiz kılan bir `[String: AdaptyCustomAsset]` sözlüğü. Bkz. [Varlıkları özelleştir](#customize-assets). | | **timerResolver** | isteğe bağlı | Geliştirici tanımlı zamanlayıcılar için bitiş tarihlerini sağlayan, `AdaptyTimerResolver` protokolüne uyan bir nesne. Bkz. [Geliştirici tanımlı zamanlayıcıları ayarla](#set-up-developer-defined-timers). | Yüklendikten sonra, [flow/paywall'ı gösterin](ios-present-paywalls). ## Varsayılan kitle için bir flow veya paywall alarak daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında yüklenir, dolayısıyla bu süreci hızlandırmak için özel bir şey yapmanız gerekmez. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall'ın yüklenmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine pürüzsüz bir kullanıcı deneyimi sunmak amacıyla varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın `getFlow` metoduyla flow veya paywall getirmek olduğunu unutmamak önemlidir. Bu konuda yukarıdaki [Paywall Bilgilerini Getirme](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümüne bakabilirsiniz. :::warning `getFlow` kullanmanızı neden öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedeflemenin kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'u görecektir; bu da ülkelere, pazarlama attribution'ına veya kendi özel özniteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları göze alarak daha hızlı flow veya paywall yükleme avantajından yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) anlatılan `getFlow` metodunu kullanmaya devam edin. ::: ```swift showLineNumbers Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow case let .failure(error): // handle the error } } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için önbelleği kullanmak güvenlidir.</p><p></p><p>Önbellek, uygulama yeniden başlatıldığında temizlenmez; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel olarak temizlendiğinde sıfırlanır.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Paywall/flow'unuzdaki görsel ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leri aracılığıyla hedefleyerek davranışlarını özelleştirebilirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID ayarlamanız](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video göster. - Uzaktan yüklenen ana görsel yüklenirken yerel bir önizleme görseli göster. - Video oynatılmadan önce bir önizleme görseli göster. - Oynatıcının video yüklenmeden önce düzen alanını ayırabilmesi için videonun piksel çözünürlüğünü belirt (en-boy oranı = `width / height`). Atlamak için `nil` geçir. Aşağıda, özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğine dair bir örnek yer alıyor: ```swift showLineNumbers let customAssets: [String: AdaptyCustomAsset] = [ // Show a local image using a custom ID "custom_image": .image( .uiImage(value: UIImage(named: "image_name")!) ), // Show a local preview image while a remote main image is loading "hero_image": .image( .remote( url: URL(string: "https://example.com/image.jpg")!, preview: UIImage(named: "preview_image") ) ), // Show a local video with a preview image and a known resolution "hero_video": .video( .file( url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!, preview: .uiImage(value: UIImage(named: "video_preview")!), resolution: CGSize(width: 1080, height: 1920) ) ), ] let flowConfig = try await AdaptyUI.getFlowConfiguration( forFlow: flow, assetsResolver: customAssets ) ``` :::note Bir öğe bulunamazsa, paywall/flow varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `AdaptyTimerResolver` protokolünü uygulayan bir nesne oluşturun. Bu nesne, her özel zamanlayıcının nasıl render edileceğini tanımlar. İsterseniz bu protokole zaten uyan bir `[String: Date]` sözlüğünü doğrudan kullanabilirsiniz. İşte bir örnek: ```swift showLineNumbers @MainActor struct AdaptyTimerResolverImpl: AdaptyTimerResolver { func timerEndAtDate(for timerId: String) -> Date { switch timerId { case "CUSTOM_TIMER_6H": Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours case "CUSTOM_TIMER_NY": Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0) default: Date(timeIntervalSinceNow: 3600.0) // 1 hour } } } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `timerResolver`, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Zamanlayıcının bitiş anına, örneğin Yılbaşı'na kadar kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcı paywall'ı açtığında başlayan 6 saatlik sürede kalan zaman. </SDKv4> <SDKv3> [Adapty Kontrol Paneli'nde Paywall Builder ile paywallınızın görsel kısmını tasarladıktan sonra](adapty-paywall-builder), bunu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkilendirilmiş paywall'ı ve görünüm yapılandırmasını almaktır. Bu konunun Paywall Builder ile özelleştirilmiş paywalllar için geçerli olduğunu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, [Remote config paywalllar için paywallları ve ürünleri getirme](fetch-paywalls-and-products) bölümüne bakın. :::tip Mobil uygulamanızda Adapty SDK'nın gerçek bir entegrasyonunu görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma işlemleri ve diğer temel işlevleri gösteren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall göstermeye başlamadan önce</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünlerinizi buna ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı bunlara ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-ios)'yı yükleyin. </details> ## Paywall Builder ile tasarlanan paywallı getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), onu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir paywall, hem paywallda neyin gösterileceğini hem de nasıl gösterileceğini içerir. Bununla birlikte, ID'sini placement aracılığıyla, görünüm yapılandırmasını ise ayrıca almanız ve ardından uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, kullanıcıya sunmadan önce görsellerin indirilmesine yeterince zaman tanımak amacıyla paywallı ve [görünüm yapılandırmasını](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız önemlidir. Paywall almak için `getPaywall` metodunu kullanın: <Tabs> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall("YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements) kimliği. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) kimliği. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes).</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olması durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbellekte veri varsa döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriyi almayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının kısıtlı olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>İşlemin arka planda farklı isteklerden oluşabileceği nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------- | | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. | ## Paywall Builder ile tasarlanmış paywallın görünüm yapılandırmasını çekme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse görünüm yapılandırması çekilemez. ::: Paywall'ı çektikten sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir görünüm yapılandırması içerip içermediğini kontrol edin. Bu, paywall'ı nasıl göstereceğiniz konusunda size rehberlik eder. Görünüm yapılandırması mevcutsa Paywall Builder paywall'ı olarak ele alın; değilse [remote config paywall'ı olarak işleyin](present-remote-config-paywalls). Görünüm yapılandırmasını yüklemek için `getPaywallConfiguration` metodunu kullanın. ```swift showLineNumbers guard paywall.hasViewConfiguration else { // use your custom logic return } do { let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, products: products ) // use loaded configuration } catch { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------------- | :---------- | | **paywall** | zorunlu | İstenen paywall için controller almak üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu metot için zaman aşımı sınırını belirler. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür. İşlem arka planda birden fazla istekten oluşabileceğinden, bu metot nadir durumlarda `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir. | | **products** | isteğe bağlı | Ekranda ürünlerin görüntülenme süresini optimize etmek için `AdaptyPaywallProduct` nesnelerinden oluşan bir dizi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve yerel ayar kodlarını doğru kullanmayı [burada](localizations-and-locale-codes) öğrenin. ::: Yüklendikten sonra [paywallı sunun](ios-present-paywalls). ## Daha hızlı getirmek için varsayılan kitle paywallını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Paywalllar genellikle neredeyse anında getirilir, bu nedenle bu süreci hızlandırmak konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywalliniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesine ait paywall'unu getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgisini Getirme](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklandığı gibi `getPaywall` metoduyla paywall getirmek olduğunu bilmek önemlidir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmemiş paywalllarla sorun yaşamasını kabul etmek durumunda kalırsınız. - **Hedefleme kaybı**: Tüm kullanıcılar **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize göre) kaybetmeniz anlamına gelir. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, aşağıdaki gibi `getPaywallForDefaultAudience` metodunu kullanın. Aksi takdirde [yukarıda](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu tercih edin. ::: ```swift showLineNumbers Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` :::note `getPaywallForDefaultAudience` metodu iOS SDK 2.11.2 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) kimliği. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) kimliği. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes).</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olması durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbellekte veri varsa döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriyi almayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video göstermek. - Uzak ana görsel yüklenirken yerel bir önizleme görseli göstermek. - Bir video başlamadan önce önizleme görseli göstermek. :::important Bu özelliği kullanmak için Adapty iOS SDK'yı 3.7.0 veya daha yüksek bir sürüme güncelleyin. ::: Özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```swift showLineNumbers let customAssets: [String: AdaptyCustomAsset] = [ // Özel bir kimlik kullanarak yerel bir görsel göster "custom_image": .image( .uiImage(value: UIImage(named: "image_name")!) ), // Uzak ana görsel yüklenirken yerel bir önizleme görseli göster "hero_image": .image( .remote( url: URL(string: "https://example.com/image.jpg")!, preview: UIImage(named: "preview_image") ) ), // Önizleme görseli olan yerel bir video göster "hero_video": .video( .file( url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!, preview: .uiImage(value: UIImage(named: "video_preview")!) ) ), ] let paywallConfig = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, assetsResolver: customAssets ) ``` :::note Bir varlık bulunamazsa paywall varsayılan görünümüne geri döner. ::: ## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\} Mobil uygulamanızda özel zamanlayıcılar kullanmak için `AdaptyTimerResolver` protokolünü uygulayan bir nesne oluşturun. Bu nesne, her özel zamanlayıcının nasıl görüntüleneceğini tanımlar. Tercih ederseniz, bu protokole zaten uygun olduğu için doğrudan bir `[String: Date]` sözlüğü de kullanabilirsiniz. İşte bir örnek: ```swift showLineNumbers @MainActor struct AdaptyTimerResolverImpl: AdaptyTimerResolver { func timerEndAtDate(for timerId: String) -> Date { switch timerId { case "CUSTOM_TIMER_6H": Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 saat case "CUSTOM_TIMER_NY": Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0) default: Date(timeIntervalSinceNow: 3600.0) // 1 saat } } } ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `timerResolver`, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Yılbaşı gibi zamanlayıcının bitiş anına kadar kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının paywall'ı açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman. </SDKv3> --- # File: ios-present-paywalls --- --- title: "Flow ve paywallları görüntüleme - iOS" description: "iOS uygulamanızda kullanıcılara flow ve paywallları sunun." --- <SDKv4> <MethodPromo method="getFlow" label="Flow ve paywallları görüntüle" /> Bir flow veya paywall oluştturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yok. Söz konusu flow veya paywall, içinde neyin gösterileceğini ve nasıl gösterileceğini zaten içeriyor. Aşağıda kullanılan `AdaptyUI.FlowConfiguration` nesnesini edinmek için [Flow ve paywallları getir](get-pb-paywalls) sayfasına bakın. ## SwiftUI'da flow ve paywallları sunma \{#present-flows-and-paywalls-in-swiftui\} ### Ekranda modal görünüm olarak göster \{#present-as-a-modal-view\} Bir flow veya paywall'ı cihaz ekranında modal görünüm olarak göstermek için SwiftUI'da `.flow` modifier'ını kullanın. En temel çağrı; `isPresented`, `flowConfiguration` ve beş zorunlu callback'i gerektirir: ```swift showLineNumbers title="SwiftUI" .flow( isPresented: $flowPresented, flowConfiguration: <AdaptyUI.FlowConfiguration>, didFinishPurchase: { _, _ in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { _, _ in /* handle the error */ }, didFinishRestore: { _ in /* check access level and dismiss */ }, didFailRestore: { _ in /* handle the error */ }, didReceiveError: { _ in flowPresented = false } ) ``` Daha fazla kontrol için, buton tıklamalarını yönetmek amacıyla `didPerformAction` gibi isteğe bağlı callback'ler ekleyin: ```swift showLineNumbers title="SwiftUI" @State var flowPresented = false // ensure that you manage this variable state and set it to `true` at the moment you want to show the flow or paywall var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: <AdaptyUI.FlowConfiguration>, didPerformAction: { action in switch action { case .close: flowPresented = false default: // Handle other actions break } }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) } ``` (empty input — nothing to translate) | Parametre | Zorunlu | Açıklama | |:-----------------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | zorunlu | Flow veya paywall ekranının görüntülenip görüntülenmediğini yöneten bir binding. | | **flowConfiguration** | zorunlu | Flow veya paywallın görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. `AdaptyUI.getFlowConfiguration(forFlow:)` metodunu kullanın. Daha fazla bilgi için [Flow ve paywall'ları alma](get-pb-paywalls) bölümüne bakın. | | **didFinishPurchase** | zorunlu | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. Flow otomatik olarak kapanmaz — burada sunum binding'inizi `false` olarak ayarlayabilir ya da hiçbir şey yapmayarak flow'un satın alma sonrasında devam etmesine izin verebilirsiniz. | | **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. | | **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. | | **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. | | **didReceiveError** | zorunlu | Bir render hatası veya flow scriptinden kaynaklanan bir çalışma zamanı hatası için çağrılır (örneğin, bir JavaScript istisnası, `AdaptyUIError` kodu `4105`). Render hataları için [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. | | **fullScreen** | isteğe bağlı | Flow veya paywallın tam ekran modunda mı yoksa sayfa olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. | | **didAppear** | isteğe bağlı | Flow veya paywall görünümü sunulduğunda çağrılır. | | **didDisappear** | isteğe bağlı | Flow veya paywall görünümü kapatıldığında çağrılır. | | **didPerformAction** | isteğe bağlı | Kullanıcı bir butona tıkladığında çağrılır. `close` ve `openURL` olmak üzere iki action ID önceden tanımlanmıştır; diğerleri özelleştirilebilir ve builder'da ayarlanabilir. | | **didSelectProduct** | isteğe bağlı | Kullanıcı veya sistem tarafından satın almak üzere bir ürün seçildiğinde çağrılır. | | **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. | | **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. | | **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. | | **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hata oluştuğunda çağrılır. Yeniden yüklemeyi denemek için `true` döndürün. | | **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. | | **showAlertItem** | isteğe bağlı | Flow veya paywallın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir binding. | | **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü render etmek için kullanılan bir fonksiyon. | | **placeholderBuilder** | isteğe bağlı | Flow veya paywall yüklenirken placeholder görünümünü render etmek için kullanılan bir fonksiyon. Varsayılan olarak `ProgressView` kullanılır. | iOS olaylarını işleme konusundaki parametreler hakkında daha fazla bilgi için [iOS - Olayları İşleme](ios-handling-events) konusuna bakın. ### Modal olmayan görünüm olarak sunma \{#present-as-a-non-modal-view\} Flow'ları ve paywall'ları uygulamanızın navigasyon akışında navigasyon hedefleri veya satır içi görünümler olarak da sunabilirsiniz. SwiftUI görünümlerinizde doğrudan `AdaptyFlowView` kullanın: ```swift showLineNumbers title="SwiftUI" AdaptyFlowView( flowConfiguration: <AdaptyUI.FlowConfiguration>, didFinishPurchase: { product, purchaseResult in // Dismiss the view, or do nothing to let the flow continue }, didFailPurchase: { product, error in // Handle purchase failure }, didFinishRestore: { profile in // Handle successful restore }, didFailRestore: { error in // Handle restore failure }, didReceiveError: { error in // Handle the error (rendering or JS exception from the flow script). } ) ``` ## Flow'ları ve paywallları UIKit'te sunma \{#present-flows-and-paywalls-in-uikit\} Flow'u veya paywall'ı cihaz ekranında görüntülemek için şu adımları izleyin: 1. Görüntülemek istediğiniz görsel flow'u `AdaptyUI.flowController(with:delegate:)` metodunu kullanarak başlatın: ```swift showLineNumbers title="Swift" import AdaptyUI let visualFlow = try AdaptyUI.flowController( with: <AdaptyUI.FlowConfiguration>, delegate: <AdaptyFlowControllerDelegate> ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------- | :---------- | | **flowConfiguration** | zorunlu | Akış veya paywallın görsel detaylarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. `AdaptyUI.getFlowConfiguration(forFlow:)` metodunu kullanın. Daha fazla bilgi için [Flow ve paywallları alma](get-pb-paywalls) konusuna bakın. | | **delegate** | zorunlu | Flow ve paywall olaylarını dinlemek için kullanılan `AdaptyFlowControllerDelegate`. Daha fazla bilgi için [Flow & paywall olaylarını yönetme](ios-handling-events) konusuna bakın. | Döndürür: | Nesne | Açıklama | | :---------------------- | :------------------------------------------------------- | | **AdaptyFlowController** | İstenen flow veya paywall ekranını temsil eden bir nesne. | 2. Nesne başarıyla oluşturulduktan sonra cihazın ekranında görüntüleyebilirsiniz: ```swift showLineNumbers title="Swift" present(visualFlow, animated: true) ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek bir örnek görmek ister misiniz? Tam kurulumu, paywall görüntüleme, satın alma yapma ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: </SDKv4> <SDKv3> Paywall Builder ile bir paywall özelleştirdiyseniz, onu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. `AdaptyUI.PaywallConfiguration` nesnesini almak için bkz. [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls). ## SwiftUI'da paywallları sunma \{#present-paywalls-in-swiftui\} ### Cihaz ekranında modal görünüm olarak sunma \{#present-as-a-modal-view\} Görsel paywallı cihaz ekranında modal görünüm olarak göstermek için SwiftUI'da `.paywall` modifier'ını kullanın: ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false // ensure that you manage this variable state and set it to `true` at the moment you want to show the paywall var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishPurchase: { product, profile in paywallPresented = false }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } ) } ``` Parameters: | Parametre | Zorunlu | Açıklama | |:----------------------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | zorunlu | Paywall ekranının görüntülenip görüntülenmeyeceğini yöneten bir binding. | | **paywallConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. | | **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. | | **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. | | **didFailRendering** | zorunlu | Arayüz oluşturulurken bir hata meydana gelirse çağrılır. Bu durumda [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. | | **fullScreen** | isteğe bağlı | Paywallın tam ekran modunda mı yoksa modal olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. | | **didAppear** | isteğe bağlı | Paywall görünümü sunulduğunda çağrılır. | | **didDisappear** | isteğe bağlı | Paywall görünümü kapatıldığında çağrılır. | | **didPerformAction** | isteğe bağlı | Kullanıcı bir düğmeye tıkladığında çağrılır. Farklı düğmelerin farklı aksiyon ID'leri vardır. `close` ve `openURL` olmak üzere iki aksiyon ID'si önceden tanımlıdır; diğerleri özeldir ve builder'da ayarlanabilir. | | **didSelectProduct** | isteğe bağlı | Bir ürün satın almak üzere seçildiyse (kullanıcı veya sistem tarafından) bu callback çağrılır. | | **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma işlemine başladığında çağrılır. | | **didFinishPurchase** | isteğe bağlı | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. | | **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. | | **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme işlemine başladığında çağrılır. | | **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hata oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. | | **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. | | **showAlertItem** | isteğe bağlı | Paywallın üzerindeki uyarı öğelerinin görüntülenmesini yöneten bir binding. | | **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmaya yarayan bir fonksiyon. | | **placeholderBuilder** | isteğe bağlı | Paywall yüklenirken yer tutucu görünümünü oluşturmaya yarayan bir fonksiyon. | iOS olaylarını işleme hakkında parametreler için [iOS - Olayları işleme](ios-handling-events) konusuna bakın. ### Kalıcı olmayan görünüm olarak sunma \{#present-as-a-non-modal-view\} Paywall'ları uygulamanızın navigasyon akışında bir navigasyon hedefi veya satır içi görünüm olarak da sunabilirsiniz. SwiftUI görünümlerinizde doğrudan `AdaptyPaywallView` kullanın: ```swift showLineNumbers title="SwiftUI" AdaptyPaywallView( paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didFailPurchase: { product, error in // Handle purchase failure }, didFinishRestore: { profile in // Handle successful restore }, didFailRestore: { error in // Handle restore failure }, didFailRendering: { error in // Handle rendering error } ) ``` ## UIKit'te paywall'ları sunma \{#present-paywalls-in-uikit\} Paywall'ı cihaz ekranında görüntülemek için şunları yapın: 1. Görüntülemek istediğiniz paywall'ı `.paywallController(for:products:viewConfiguration:delegate:)` metodunu kullanarak başlatın: ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( with: <paywall configuration object>, delegate: <AdaptyPaywallControllerDelegate> ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------- | :---------- | | **paywall configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **delegate** | zorunlu | Paywall olaylarını dinlemek için bir `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. | Döner: | Nesne | Açıklama | | :---------------------- | :--------------------------------------------------- | | **AdaptyPaywallController** | İstenen paywall ekranını temsil eden bir nesne | 2. Nesne başarıyla oluşturulduktan sonra cihaz ekranında gösterebilirsiniz: ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Kurulumun tamamını, paywall gösterimi, satın alma işlemleri ve diğer temel işlevler dahil olmak üzere ele alan [örnek uygulamalarımıza](sample-apps) göz atın. ::: </SDKv3> --- # File: handle-paywall-actions --- --- title: "Flow aksiyonlarına yanıt verme - iOS" description: "iOS uygulamanızda paywall ve onboarding flow'larındaki buton aksiyonlarını yönetin ve kullanıcı girdilerini işleyin." --- <SDKv4> Adapty Flow Builder veya Paywall Builder kullanarak flow veya paywall oluşturuyorsanız, butonları doğru şekilde yapılandırmanız kritik önem taşır: 1. [Paywall Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden var olan bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulama kodunuzu yazın. Bu kılavuz, özel ve önceden var olan eylemlerin kodunuzda nasıl işleneceğini gösterir. :::warning **Yalnızca flow/paywall kapanışları ve URL açma işlemleri otomatik olarak yönetilir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun bir yanıt uygulaması gerektirir. ::: :::note iOS SDK, `AdaptySystemRequestsHandler` aracılığıyla bildirim izinleri veya kamera erişimi gibi sistem izin isteklerine yanıt verebilir. Flow'lar henüz bu tür istekleri tetiklemiyor, dolayısıyla şimdilik bunları ele almanıza gerek yok. ::: ## Flow ve paywallları kapatma \{#close-flows-and-paywalls\} Flow veya paywallınıza bir kapatma düğmesi eklemek için: 1. Builder'da bir düğme ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda `close` eylemi için bir handler uygulayın. :::info iOS SDK'da `close` eylemi, flow veya paywall'ı varsayılan olarak kapatır. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir flow'u kapatmak başka bir flow'u açmayı tetikleyebilir. ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false // dismiss the flow or paywall default: break } }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) ``` ## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde ele alın. ::: Flow veya paywall'ınızdan bağlantı açan bir düğme eklemek için (örneğin, **Terms of use** veya **Privacy policy**): 1. Builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi bir tarayıcıda açan `openURL` eylemi için bir işleyici uygulayın. :::info iOS SDK'da `openURL` eylemi, varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case let .openURL(url): UIApplication.shared.open(url, options: [:]) // default behavior default: break } }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Başka eylemleri yönetecek bir düğme eklemek için: 1. Oluşturucuda bir düğme ekleyin, **Custom** eylemini atayın ve bir ID belirleyin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi seti ya da tek seferlik satın alma seçenekleriniz varsa, başka bir flow veya paywall açacak bir düğme ekleyebilirsiniz: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case let .custom(id): if id == "openNewPaywall" { // Display another flow or paywall } default: break } }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) ``` </SDKv4> <SDKv3> Adapty paywall builder kullanarak paywall oluşturuyorsanız, butonları doğru şekilde yapılandırmanız kritik önem taşır: 1. [Paywall builder'da bir buton](paywall-buttons) ekleyin ve bu butona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi uygulamanızın kodunda işleyecek kodu yazın. Bu kılavuz, özel ve mevcut eylemleri kodunuzda nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar, geri yüklemeler, paywall kapanmaları ve URL açma işlemleri otomatik olarak yönetilir.** Diğer tüm buton eylemleri için uygulama kodunda uygun yanıt implementasyonu gereklidir. ::: ## Paywallları kapatma \{#close-paywalls\} Paywallınızı kapatacak bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda, paywall'ı kapatan `close` eylemi için bir işleyici uygulayın. :::info iOS SDK'da `close` eylemi, varsayılan olarak paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywall'ı kapatmak başka bir paywall'ın açılmasını tetikleyebilir. ::: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case .close: controller.dismiss(animated: true) // default behavior break } } ``` ## Paywalllardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (ör. kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemine sahip düğmelerle aynı şekilde yönetin. ::: Paywallınızdan bağlantı açan bir düğme eklemek için (ör. **Kullanım Koşulları** veya **Gizlilik Politikası**): 1. Paywall builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info iOS SDK'da `openUrl` eylemi, varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case let .openURL(url): UIApplication.shared.open(url, options: [:]) // default behavior break } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` eylemi için bir işleyici uygulayın. ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case .login: // Show a login screen let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") controller.present(loginVC, animated: true) } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer eylemleri yöneten bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin, **Custom** eylemini atayın ve bir ID belirleyin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa başka bir paywall görüntüleyen bir düğme ekleyebilirsiniz: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case let .custom(id): if id == "openNewPaywall" { // Başka bir paywall göster } } break } } ``` </SDKv3> --- # File: ios-handling-events --- --- title: "Flow ve paywall olaylarını yönetme - iOS" description: "iOS uygulamanızda flow ve paywall olaylarını yönetin." --- <SDKv4> :::important Bu kılavuz; satın almalar, geri yüklemeler, ürün seçimi ve paywall görüntüleme için olay yönetimini kapsar. Bunların yanı sıra buton işlemlerini de (paywall kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton eylemlerini yönetme kılavuzumuza](handle-paywall-actions) bakın. ::: Flow'lar ve paywalllar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar arasında düğme basışları (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve satın alma ile ilgili eylemler hakkında bildirimler bulunur. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek dünya örneği görmek ister misiniz? Paywall görüntüleme, satın alma yapma ve diğer temel işlevler dahil olmak üzere tam kurulumu sergileyen [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## SwiftUI'da olayları yönetme \{#handling-events-in-swiftui\} Mobil uygulamanızdaki flow veya paywall ekranında gerçekleşen süreçleri kontrol etmek ya da izlemek için SwiftUI'da `.flow` modifier'ını kullanın: ```swift showLineNumbers title="Swift" @State var flowPresented = false var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false case let .openURL(url): // handle opening the URL (incl. for terms and privacy) default: // handle other actions } }, didSelectProduct: { product in /* Handle the event */ }, didStartPurchase: { product in /* Handle the event */ }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didStartRestore: { /* Handle the event */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false }, didFailLoadingProducts: { error in // Return `true` to retry loading return false } ) } ``` Yalnızca ihtiyacınız olan closure parametrelerini kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz. | Parametre | Zorunlu | Açıklama | |:-----------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | zorunlu | Flow veya paywall ekranının görüntülenip görüntülenmeyeceğini yöneten bir binding. | | **flowConfiguration** | zorunlu | Flow veya paywallın görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. Daha fazla bilgi için [Flow ve paywall'ları al](get-pb-paywalls) bölümüne bakın. | | **didFinishPurchase** | zorunlu | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. Flow otomatik olarak kapanmaz — burada presentation binding'inizi `false` olarak ayarlayın ya da flow'un satın alma sonrasında devam etmesi için hiçbir şey yapmayın. | | **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. | | **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. | | **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. | | **didReceiveError** | zorunlu | Flow bir render hatası veya flow betiğinden kaynaklanan bir çalışma zamanı hatasıyla karşılaştığında çağrılır (örneğin, bir JavaScript istisnası, `AdaptyUIError` kodu `4105`). Render hatası durumunda [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. | | **placeholderBuilder** | isteğe bağlı | Flow veya paywall yüklenirken yer tutucu görünümü oluşturmak için kullanılan bir fonksiyon. Varsayılan olarak `ProgressView` kullanılır. | | **fullScreen** | isteğe bağlı | Flow veya paywallın tam ekran modunda mı yoksa bir sheet olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. | | **didAppear** | isteğe bağlı | Flow veya paywall görünümü ekranda göründüğünde çağrılır. | | **didDisappear** | isteğe bağlı | Flow veya paywall görünümü kapatıldığında çağrılır. | | **didPerformAction** | isteğe bağlı | Kullanıcı bir butona tıkladığında çağrılır. İki eylem kimliği önceden tanımlıdır: `close` ve `openURL`; diğerleri özeldir ve builder'da ayarlanabilir. | | **didSelectProduct** | isteğe bağlı | Kullanıcı veya sistem tarafından satın alma için bir ürün seçildiğinde çağrılır. | | **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. | | **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. | | **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. | | **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hatalar oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. | | **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. | | **showAlertItem** | isteğe bağlı | Flow veya paywallın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir binding. | | **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmak için kullanılan bir fonksiyon. | ## UIKit'te olayları yönetme \{#handling-events-in-uikit\} UIKit uygulamalarında olaylar, `AdaptyFlowControllerDelegate` protokolü aracılığıyla yönetilir. `AdaptyFlowController`'ı `AdaptyFlowControllerDelegate` ile nasıl kuracağınızı öğrenmek için [Flow ve paywallları gösterme - iOS](ios-present-paywalls) sayfasına bakın. Protokol 13 metot tanımlar. Bunların dördünün varsayılan uygulaması yoktur ve uyum sağlarken mutlaka uygulanması gerekir: `didFinishPurchase`, `didFailPurchase`, `didFinishRestoreWith` ve `didFailRestoreWith`. Geri kalanlar varsayılan olarak işlemsiz (no-op) uygulamalarla gelir ve özel davranış istediğinizde bunları geçersiz kılabilirsiniz. Metotlar aşağıda amaca göre gruplandırılmıştır. ### Yaşam Döngüsü \{#lifecycle\} ```swift showLineNumbers title="Swift" func flowControllerDidAppear(_ controller: AdaptyFlowController) { } func flowControllerDidDisappear(_ controller: AdaptyFlowController) { } ``` Bu metodlar, flow veya paywall görünümü gösterildiğinde ya da kapatıldığında tetiklenir. ### Kullanıcı eylemleri \{#user-actions\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didPerform action: AdaptyUI.Action ) { } ``` `AdaptyUI.Action` durumları: - `.close` — varsayılan davranış, controller'ı kapatır. Controller'ı ekranda tutmak veya ekstra temizlik işlemleri yapmak için bu davranışı override edebilirsiniz. - `.openURL(url:)` — varsayılan davranış, URL'yi `UIApplication.shared.open(...)` ile açar. - `.custom(id:)` — builder'da özel bir eylem ID'si atanmış butonlar için tetiklenir. ### Ürün seçimi \{#product-selection\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didSelectProduct product: AdaptyPaywallProduct ) { } ``` Kullanıcı veya sistem tarafından satın alma için bir ürün seçildiğinde çağrılır. Ürün, tam teklif bilgisini taşır (v4'te uygunluk otomatik olarak belirlenir — ayrı bir `AdaptyPaywallProductWithoutDeterminingOffer` türü yoktur). ### Satın alma etkinlikleri \{#purchase-events\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didStartPurchase product: AdaptyPaywallProduct ) { } func flowController( _ controller: AdaptyFlowController, didFinishPurchase product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { if !purchaseResult.isPurchaseCancelled { controller.dismiss(animated: true) // or do nothing to let the flow continue } } func flowController( _ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` `didFinishPurchase` ve `didFailPurchase` için varsayılan bir uygulama yoktur ve bunların implemente edilmesi zorunludur. Controller, başarılı bir satın alma işleminin ardından kendini kapatmaz — uygun olduğunda `controller.dismiss(animated:)` çağırın ya da çok ekranlı bir flow devam etsin istiyorsanız hiçbir şey yapmayın. ### Geri yükleme olayları \{#restore-events\} ```swift showLineNumbers title="Swift" func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { } func flowController( _ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile ) { } func flowController( _ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError ) { } ``` `didFinishRestoreWith` ve `didFailRestoreWith` için varsayılan bir uygulama bulunmaz. Controller'ı kapatmadan önce döndürülen `AdaptyProfile`'ın istediğiniz access level'ı içerip içermediğini kontrol edin. ### Flow hataları ve ürün yükleme hataları \{#flow-errors-and-product-loading-errors\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didReceiveError error: AdaptyUIError ) { } func flowController( _ controller: AdaptyFlowController, didFailLoadingProductsWith error: AdaptyError ) -> Bool { // Return `true` to retry product loading; default returns `false`. return false } func flowController( _ controller: AdaptyFlowController, didPartiallyLoadProducts failedIds: [String] ) { } ``` `didReceiveError`, render hataları ve flow script'inden gelen çalışma zamanı hataları için tetiklenir (JavaScript istisnaları, `AdaptyUIError` kodu `4105`). Render hataları için [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. Yükleme hataları için geçici ağ sorunlarında yeniden denemek amacıyla `didFailLoadingProductsWith` fonksiyonundan `true` döndürün. ### Web ödeme navigasyonu \{#web-payment-navigation\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, error: AdaptyError? ) { } ``` Web ödeme navigasyonu tamamlandıktan sonra çağrılır; başarılı veya başarısız olup olmadığına bakılmaksızın. </SDKv4> <SDKv3> :::important Bu kılavuz, satın almalar, yenileme işlemleri, ürün seçimi ve paywall oluşturma için event yönetimini kapsamaktadır. Ayrıca buton işlemlerini de (paywallı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton eylemlerini yönetme kılavuzumuza](handle-paywall-actions) bakın. ::: Paywall Builder ile yapılandırılmış paywalllar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; düğme basışlarını (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili işlemlere dair bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Bu kılavuz yalnızca Adapty SDK v3.0 veya sonrasını gerektiren **yeni Paywall Builder paywallları** içindir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek dünyadan bir örnekle görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma yapma ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## SwiftUI'da olayları yönetme \{#handling-events-in-swiftui\} Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için SwiftUI'da `.paywall` modifierını kullanın: ```swift showLineNumbers title="Swift" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywall: paywall, viewConfiguration: viewConfig, didPerformAction: { action in switch action { case .close: paywallPresented = false case let .openURL(url): // URL açmayı yönet (şartlar ve gizlilik dahil) default: // diğer eylemleri yönet } }, didSelectProduct: { /* Olayı yönet */ }, didStartPurchase: { /* Olayı yönet */ }, didFinishPurchase: { product, info in /* Olayı yönet */ }, didFailPurchase: { product, error in /* Olayı yönet */ }, didStartRestore: { /* Olayı yönet */ }, didFinishRestore: { /* Olayı yönet */ }, didFailRestore: { /* Olayı yönet */ }, didFailRendering: { error in paywallPresented = false }, didFailLoadingProducts: { error in return false } ) } ``` Yalnızca ihtiyacınız olan closure parametrelerini kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz. Bu durumda kullanılmayan closure parametreleri oluşturulmaz. | Parametre | Zorunlu | Açıklama | |:----------------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | zorunlu | Paywall ekranının görüntülenip görüntülenmediğini yöneten bir bağlayıcı. | | **paywallConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` metodunu kullanın. Daha fazla ayrıntı için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **didFailPurchase** | zorunlu | Bir satın alma işlemi hatalar nedeniyle başarısız olduğunda çağrılır (örn. ödemeye izin verilmemesi, ağ sorunları, geçersiz ürün). Kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz. | | **didFinishRestore** | zorunlu | Satın alma işlemi başarıyla tamamlandığında çağrılır. | | **didFailRestore** | zorunlu | Bir satın alma işlemi geri yüklenirken hata oluştuğunda çağrılır. | | **didFailRendering** | zorunlu | Arayüz oluşturulurken hata oluşursa çağrılır. Bu durumda [Adapty Destek ekibiyle iletişime geçin](mailto:support@adapty.io). | | **fullScreen** | isteğe bağlı | Paywallın tam ekran modunda mı yoksa modal olarak mı görüneceğini belirler. Varsayılan değer `true`. | | **didAppear** | isteğe bağlı | Paywall görünümü ekranda belirdiğinde çağrılır. Ayrıca kullanıcı paywall içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) tıkladığında ve bir web paywall uygulama içi tarayıcıda açıldığında da çağrılır. | | **didDisappear** | isteğe bağlı | Paywall görünümü kapatıldığında çağrılır. Ayrıca paywall'dan açılan bir [web paywall](web-paywall#step-2a-add-a-web-purchase-button) uygulama içi tarayıcıda ekrandan kaybolduğunda da çağrılır. | | **didPerformAction** | isteğe bağlı | Kullanıcı bir düğmeye tıkladığında çağrılır. Farklı düğmelerin farklı eylem kimlikleri vardır. `close` ve `openURL` olmak üzere iki eylem kimliği önceden tanımlanmıştır; diğerleri özeldir ve builder'da ayarlanabilir. | | **didSelectProduct** | isteğe bağlı | Bir ürün satın almak için seçildiğinde (kullanıcı veya sistem tarafından) bu callback çağrılır. | | **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. | | **didFinishPurchase** | isteğe bağlı | Satın alma işlemi başarıyla tamamlandığında çağrılır. | | **didFinishWebPaymentNavigation** | isteğe bağlı | Satın alma için bir [web paywall](web-paywall) açılmaya çalışıldıktan sonra, başarılı olsun ya da olmasın, çağrılır. | | **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. | | **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hatalar oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. | | **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. | | **showAlertItem** | isteğe bağlı | Paywall'ın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir bağlayıcı. | | **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmaya yarayan bir fonksiyon. | | **placeholderBuilder** | isteğe bağlı | Paywall yüklenirken yer tutucu görünümü oluşturmaya yarayan bir fonksiyon. | ## UIKit'te olayları yönetme \{#handling-events-in-uikit\} Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyPaywallControllerDelegate` metodlarını uygulayın. ### Kullanıcı kaynaklı olaylar \{#user-generated-events\} #### Ürün seçimi \{#product-selection\} Bir kullanıcı satın alma için bir ürün seçerse bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController(_ controller: AdaptyPaywallController, didStartPurchase product: AdaptyPaywallProduct) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web paywall kullanarak satın alma başlatıldı \{#started-purchase-using-a-web-paywall\} Bir kullanıcı [web paywall](web-paywall) kullanarak satın alma sürecini başlatırsa bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, shouldContinueWebPaymentNavigation product: AdaptyPaywallProduct ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### Başarılı veya iptal edilen satın alma \{#successful-or-canceled-purchase\} Satın alma başarılı olursa bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFinishPurchase product: AdaptyPaywallProductWithoutDeterminingOffer, purchaseResult: AdaptyPurchaseResult ) { } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "cancelled" } } ``` </Details> Bu durumda paywall ekranını kapatmanızı öneririz. Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Başarısız satın alma \{#failed-purchase\} Bir satın alma hata nedeniyle başarısız olursa bu metod çağrılır. Bu; StoreKit hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptalleri, iptal edilmiş sonuçla birlikte `didFinishPurchase` metodunu tetikler; bekleyen ödemeler ise bu metodu tetiklemez. ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın. #### Web paywall kullanarak başarısız satın alma \{#failed-purchase-using-a-web-paywall\} `Adapty.openWebPaywall()` başarısız olursa bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFailWebPaymentNavigation product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ``` </Details> #### Başarılı geri yükleme \{#successful-restore\} Satın alma geri yükleme başarılı olursa bu metod çağrılır: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFinishRestoreWith profile: AdaptyProfile ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Nasıl kontrol edileceğini öğrenmek için [Abonelik durumu](subscription-status) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} Satın alma geri yükleme başarısız olursa bu metod çağrılır: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailRestoreWith error: AdaptyError ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> ### Veri getirme ve oluşturma \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürün dizisini geçmezseniz AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa AdaptyUI hatayı bu metodu çağırarak bildirir: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailLoadingProductsWith error: AdaptyError ) -> Bool { return true } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> `true` döndürürseniz AdaptyUI isteği 2 saniye sonra tekrarlar. #### Oluşturma hataları \{#rendering-errors\} Arayüz oluşturulurken bir hata meydana gelirse bu metod tarafından bildirilir: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailRenderingWith error: AdaptyError ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> Normal bir durumda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin. </SDKv3> --- # File: ios-use-fallback-paywalls --- --- title: "iOS - Yedekleri kullan" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucuları erişilebilir değilken durumları ele alın" --- Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek JSON dosyasını proje paketinize ekleyin: XCode'da **File** menüsünü açın ve **Add Files to "YourProjectName"** seçeneğini seçin. 2. Hedef flow, paywall veya onboarding'i çekmeden **önce** `.setFallback` metodunu çağırın. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { if let urlPath = Bundle.main.url(forResource: fileName, withExtension: "json") { try await Adapty.setFallback(fileURL: urlPath) } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers if let url = Bundle.main.url(forResource: "ios_fallback", withExtension: "json") { Adapty.setFallback(fileURL: url) } ``` </TabItem> </Tabs> Parametreler: | Parametre | Açıklama | | :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **fileURL** | Yedek yapılandırma dosyasının yolu. | --- # File: localizations-and-locale-codes --- --- title: "iOS SDK'da yerelleştirme ve yerel ayar kodlarını kullanma" description: "iOS uygulamanızda global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin." --- ## Neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır; örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywallı getirmeye çalışırken bu durumla karşılaşabilirsiniz. Yerel ayar kodları karmaşık bir yapıya sahip olduğundan ve platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlarda ortak bir iç standart kullanıyoruz. Ancak bu kodların karmaşıklığı nedeniyle, sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; böylece her zaman beklediğiniz sonucu alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci taraflı SDK'dan yerel ayar koduyla bir çağrı aldığında ve bir paywallın ilgili yerelleştirmesini aramaya başladığında şu adımlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgilerle (`-`) değiştirilir. 2. Tam eşleşen yerel ayar koduna sahip yerelleştirme aranır. 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır. 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesi döndürülür. Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yöntem \{#implementing-localizations-recommended-way\} Yerelleştirmeler konusunu araştırıyorsanız, büyük ihtimalle projenizde yerelleştirilmiş string dosyalarıyla zaten çalışıyorsunuzdur. Bu durumda, her yerelleştirme için ilgili dosyalarınızdan birine hedeflenen Adapty yerel ayar kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini aşağıdaki gibi çıkarabilirsiniz: ```swift showLineNumbers // 1. Modify your Localizable.strings files /* Localizable.strings - Spanish */ adapty_paywalls_locale = "es"; /* Localizable.strings - Portuguese (Brazil) */ adapty_paywalls_locale = "pt-br"; // 2. Extract and use the locale code let locale = NSLocalizedString("adapty_paywalls_locale", comment: "") // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşım sayesinde, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği üzerinde tam kontrol sahibi olursunuz. ## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için yerel ayar kodlarını açıkça tanımlamadan da benzer (ancak özdeş olmayan) sonuçlar elde edebilirsiniz. Bu yöntemde, platformunuzun sağladığı başka nesnelerden yerel ayar kodu çıkarırsınız: ```swift showLineNumbers let locale = Locale.current.identifier // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` Bu yaklaşımı birkaç nedenden dolayı önermiyoruz: 1. iOS'ta tercih edilen diller ile mevcut yerel ayar aynı şey değildir. Yerelleştirmenin doğru seçilmesini istiyorsanız ya Apple'ın mantığına güvenmeniz gerekir (bu, yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda zaten otomatik olarak çalışır) ya da bu mantığı kendiniz yeniden oluşturmanız gerekir. 2. Adapty sunucusunun tam olarak ne alacağını öngörmek güçtür. Örneğin iOS'ta bir cihazdan `ar_OM@numbers='latn'` gibi bir yerel ayar elde edip sunucumuza göndermek mümkündür. Bu durumda aradığınız `ar-om` yerelleştirmesini değil, büyük ihtimalle beklenmedik olan `ar` yerelleştirmesini alırsınız. Bu yaklaşımı kullanmaya karar verirseniz, ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun. --- # File: ios-troubleshoot-paywall-builder --- --- title: "iOS SDK'da Paywall Builder Sorun Giderme" description: "iOS SDK'da Paywall Builder Sorun Giderme" --- Bu kılavuz, iOS SDK'da Adapty Paywall Builder ile tasarlanmış paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `getPaywallConfiguration` metodu paywall yapılandırmasını getiremiyor. **Neden**: Paywall, Paywall Builder'da cihazda görüntüleme için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Paywall görüntüleme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntüleme sayısı beklenen değerin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (iOS SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz. Paywall Builder veya Flow Builder kullanıyorsanız bu yöntem görüntüleme sayısını çiftler. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitikler otomatik olarak takip edilir, dolayısıyla bu yöntemi çağırmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (iOS SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder kaynaklı sorunlar yaşıyorsunuz. **Çözüm**: Gerekirse [geçiş kılavuzlarını](ios-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun, SDK'nın daha yeni sürümlerinde çözülmüştür. --- # File: ios-present-paywall-builder-paywalls-in-observer-mode --- --- title: "iOS SDK'da Observer modunda Paywall Builder paywalllarını sunun" description: "Daha iyi içgörüler için observer modunda PB paywalllarını nasıl sunacağınızı öğrenin." --- Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız [iOS - Present Paywall Builder paywalls](ios-present-paywalls) sayfasına bakın. ::: <SDKv4> <details> <summary>Flow sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'nin [App Store ile](initial_ios) ilk entegrasyonunu ayarlayın. 2. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. [iOS SDK kurulum kılavuzuna](sdk-installation-ios#activate-adapty-module-of-adapty-sdk) başvurun. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'ları veya paywall'ları yapılandırın](create-paywall) ve ürünleri bunlara atayın. 5. [Placement'lar oluşturun ve flow'larınızı veya paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını alın](get-pb-paywalls). </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeResolver` nesnesini uygulayın. Protokol, SDK v3 ile aynıdır — observer mode, flow ve paywall rendering arasında değişmez: ```swift showLineNumbers title="Swift" func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // call onStartPurchase / onFinishPurchase to notify AdaptyUI about the purchase progress } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // call onStartRestore / onFinishRestore to notify AdaptyUI about the restore progress } ``` 2. Çözümleyicinizi `observerModeResolver:` parametresi olarak geçirerek bir flow yapılandırma nesnesi oluşturun: ```swift showLineNumbers title="Swift" do { let flowConfiguration = try await AdaptyUI.getFlowConfiguration( forFlow: flow, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------- | | **forFlow** | zorunlu | `Adapty.getFlow(placementId:)` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. Bkz. [Flow ve paywall'ları alma](get-pb-paywalls). | | **observerModeResolver** | zorunlu | Yukarıda uyguladığınız `AdaptyObserverModeResolver`. | 3. `AdaptyUI.flowController(with:delegate:)` kullanarak flow controller'ı başlatın: ```swift showLineNumbers title="Swift" import AdaptyUI let visualFlow = try AdaptyUI.flowController( with: flowConfiguration, delegate: <AdaptyFlowControllerDelegate> ) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | **flowConfiguration** | gerekli | Flow'un görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. Bkz. [Flow ve paywallları alma](get-pb-paywalls). | | **delegate** | gerekli | Flow olaylarını dinlemek için bir `AdaptyFlowControllerDelegate`. Bkz. [Flow ve paywall olaylarını yönetme](ios-handling-events). | Döndürür: | Nesne | Açıklama | | :------------------- | :----------------------------------------------------- | | AdaptyFlowController | İstenen flow ekranını temsil eden bir nesne. | 4. Controller'ı gösterin: ```swift showLineNumbers title="Swift" present(visualFlow, animated: true) ``` :::warning [Paywallları satın alma işlemleriyle ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywall'dan geldiğini belirleyemez. ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> SwiftUI'da, resolver ile flow yapılandırmasını çekin ve `.flow` modifier'ına geçirin: ```swift showLineNumbers title="SwiftUI" @State var flowPresented = false @State var flowConfiguration: AdaptyUI.FlowConfiguration? var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false default: break } }, didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) .task { flowConfiguration = try? await AdaptyUI.getFlowConfiguration( forFlow: flow, observerModeResolver: <AdaptyObserverModeResolver> ) } } ``` `getFlowConfiguration` üzerindeki `observerModeResolver:` parametresi, render edilen flow'un özel satın alma mantığınıza uymasını sağlar — modifier'ın kendisi de tam mod ile aynı callback'leri kullanır. :::warning [Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez. ::: </TabItem> </Tabs> </SDKv4> <SDKv3> <Tabs groupId="current-os" queryString> <TabItem value="sdk3" label="Paywall Builder (SDK 3.x)" default> <details> <summary>Paywall sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu kurun. 2. Adapty SDK'yı yükleyin ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlar için [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk) belgelerine bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. Adapty Kontrol Paneli'nde [paywall'ları yapılandırın, ürünleri bunlara atayın](create-paywall) ve Paywall Builder ile özelleştirin. 5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını alın](get-pb-paywalls). </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeResolver` nesnesini uygulayın: ```swift showLineNumbers title="Swift" func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore } ``` `observerMode(didInitiatePurchase:onStartPurchase:onFinishPurchase:)` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu geri çağırıma yanıt olarak kendi özel satın alma akışınızı tetikleyebilirsiniz. `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` olayı, kullanıcının bir geri yükleme işlemi başlattığını size bildirir. Bu geri çağırıma yanıt olarak kendi özel geri yükleme akışınızı tetikleyebilirsiniz. Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, loader gösterimi gibi paywall'un düzgün çalışması için gereklidir: | Callback | Açıklama | | :----------------- | :------------------------------------------------------------------------------------------- | | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | 2. Bir paywall yapılandırma nesnesi oluşturun: ```swift showLineNumbers title="Swift" do { let paywallConfiguration = try AdaptyUI.getPaywallConfiguration( forPaywall: <paywall object>, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error } ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall** | zorunlu | İstenen paywall için bir controller elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. | | **ObserverModeResolver** | zorunlu | Önceki adımda uyguladığınız `AdaptyObserverModeResolver` nesnesi. | 3. Görüntülemek istediğiniz görsel paywallı başlatmak için `.paywallController(for:products:viewConfiguration:delegate:)` metodunu kullanın: ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( with: <paywall configuration object>, delegate: <AdaptyPaywallControllerDelegate> ) ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall Configuration** | zorunlu | Paywallın görsel detaylarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **Delegate** | zorunlu | Paywall olaylarını dinlemek için bir `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. | Döndürür: | Nesne | Açıklama | | :---------------------- | :--------------------------------------------------- | | AdaptyPaywallController | İstenen paywall ekranını temsil eden bir nesne | Nesne başarıyla oluşturulduktan sonra şu şekilde görüntüleyebilirsiniz: ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::warning [Satın alma işlemlerine paywallları bağlamayı](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywalldan geldiğini belirleyemez. ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> Görsel paywallı cihaz ekranında göstermek için SwiftUI'da `.paywall` modifier'ını kullanın: ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywallConfiguration: <paywall configuration object>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } ) } ``` (empty input — nothing to translate) | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall Configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **Products** | isteğe bağlı | Ekranda ürünlerin gösterim zamanlamasını optimize etmek için `AdaptyPaywallProduct` nesnelerinden oluşan bir dizi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **TagResolver** | isteğe bağlı | Özel etiketler ve bunların çözümlenmiş değerlerinden oluşan bir sözlük tanımlayın. Özel etiketler paywall içeriğinde yer tutucu olarak kullanılır ve paywall içinde kişiselleştirilmiş içerik sunmak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | | **ObserverModeResolver** | isteğe bağlı | Bir önceki adımda uyguladığınız `AdaptyObserverModeResolver` nesnesi | Closure parametreleri: | Closure parametresi | Açıklama | | :------------------- | :----------------------------------------------------------------------------------------- | | **didFinishRestore** | Adapty.restorePurchases() başarılı olursa bu callback çağrılır. | | **didFailRestore** | Adapty.restorePurchases() başarısız olursa bu callback çağrılır. | | **didFailRendering** | Arayüz oluşturma sırasında bir hata oluşursa bu callback çağrılır. | Diğer closure parametreleri için [iOS - Olayları işleme](ios-handling-events) konusuna bakın. :::warning [Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez. ::: </TabItem> </Tabs> </TabItem> <TabItem value="sdk2" label="Legacy Paywall Builder (SDK up to 2.x)" default> <details> <summary>Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'yi [Google Play](initial-android) ve [App Store](initial_ios) ile başlangıç entegrasyonunu yapın. 1. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özel talimatlarımıza bakın: [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) ve [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk). 2. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 3. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri bunlara atayın](create-paywall) ve Paywall Builder ile özelleştirin. 4. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement). 5. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını çekin](get-pb-paywalls). </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeDelegate` nesnesini uygulayın: ```swift showLineNumbers title="Swift" func paywallController(_ controller: AdaptyPaywallController, didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } ``` `paywallController(_:didInitiatePurchase:onStartPurchase:onFinishPurchase:)` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu olaya yanıt olarak kendi özel satın alma akışınızı tetikleyebilirsiniz. Ayrıca, satın alma sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi paywall'ın düzgün çalışması için gereklidir: | Callback | Açıklama | | :--------------- | :-------------------------------------------------------------------------------------------- | | onStartPurchase | AdaptyUI'ya satın almanın başladığını bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase | AdaptyUI'ya satın almanın tamamlandığını bildirmek için bu callback çağrılmalıdır. | 2. Görüntülemek istediğiniz görsel paywall'u `.paywallController(for:products:viewConfiguration:delegate:observerModeDelegate:)` metodunu kullanarak başlatın: ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( for: <paywall object>, products: <paywall products array>, viewConfiguration: <LocalizedViewConfiguration>, delegate: <AdaptyPaywallControllerDelegate> observerModeDelegate: <AdaptyObserverModeDelegate> ) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :----------------------- | :------- | :----------------------------------------------------------- | | **Paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. | | **Products** | isteğe bağlı | Ürünlerin ekranda gösterilme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse, AdaptyUI gerekli ürünleri otomatik olarak çeker. | | **ViewConfiguration** | zorunlu | Paywall'ın görsel ayrıntılarını içeren `AdaptyUI.LocalizedViewConfiguration` nesnesi. `AdaptyUI.getViewConfiguration(paywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywall'larını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **Delegate** | zorunlu | Paywall olaylarını dinlemek için kullanılan `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. | | **ObserverModeDelegate** | zorunlu | Bir önceki adımda uyguladığınız `AdaptyObserverModeDelegate` nesnesi. | | **TagResolver** | isteğe bağlı | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlayın. Özel etiketler, paywall içeriğinde yer tutucu görevi görür ve paywall içinde kişiselleştirilmiş içerik sunmak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. | Döndürür: | Nesne | Açıklama | | :---------------------- | :--------------------------------------------------- | | AdaptyPaywallController | İstenen paywall ekranını temsil eden bir nesne | Nesne başarıyla oluşturulduktan sonra şu şekilde görüntüleyebilirsiniz: ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::warning [Satın alma işlemlerini paywall'lara ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez. ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> Görsel paywall'ı cihaz ekranında göstermek için SwiftUI'da `.paywall` modifier'ını kullanın: ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywall: <paywall object>, configuration: <LocalizedViewConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false }, observerModeDidInitiatePurchase: { product, onStartPurchase, onFinishPurchase in // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase }, ) } ``` (empty input — nothing to translate) | Parametre | Zorunluluk | Açıklama | | :---------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall** | zorunlu | İstediğiniz paywall için bir controller elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. | | **Product** | isteğe bağlı | Ürünlerin ekranda görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse AdaptyUI, gerekli ürünleri otomatik olarak getirir. | | **Configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.LocalizedViewConfiguration` nesnesi. `AdaptyUI.getViewConfiguration(paywall:locale:)` metodunu kullanın. Daha fazla ayrıntı için [Paywall Builder paywall'larını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. | | **TagResolver** | isteğe bağlı | Özel etiketlerin ve bunların çözümlenmiş değerlerinin bir sözlüğünü tanımlayın. Özel etiketler, paywall içeriğinde yer tutucu olarak kullanılır ve paywall içinde kişiselleştirilmiş içerik için belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için Paywall Builder'daki özel etiketler konusuna bakın. | Closure parameters: | Closure parametresi | Açıklama | | :---------------------------------- | :----------------------------------------------------------------------------------------------- | | **didFinishRestore** | Adapty.restorePurchases() başarılı olursa bu callback çağrılır. | | **didFailRestore** | Adapty.restorePurchases() başarısız olursa bu callback çağrılır. | | **didFailRendering** | Arayüz oluşturma sırasında bir hata oluşursa bu callback çağrılır. | | **observerModeDidInitiatePurchase** | Bu callback, bir kullanıcı satın alma işlemi başlattığında çağrılır. | Diğer closure parametreleri için [iOS - Olayları işleme](ios-handling-events) konusuna bakın. :::warning [Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynağı olan paywall'ı belirleyemez. ::: </TabItem> </Tabs> </TabItem> </Tabs> </SDKv3> --- # File: ios-quickstart-manual --- --- title: "iOS SDK'da özel paywall'unuzda satın almaları etkinleştirme" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel iOS paywall'larınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall uygulaması üzerinde tam kontrolü elinizde tutarken Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler. :::important **Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu istiyorsanız [Adapty Flow Builder](ios-quickstart-paywalls)'ı kullanın. Flow Builder ile görsel bir no-code editörde flow'lar oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlayın \{#set-up-products\} Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de paywalllar, ürünleri almanın tek yoludur; ancak bu tasarım sayesinde uygulama kodunuza dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. - [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yapı, A/B testleri yürütmeyi ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır. Özel bir paywall kullanıyor olsanız bile bu kavramları anladığınızdan emin olun. Temelde bunlar, uygulamanızda sattığınız ürünleri yönetme biçiminizdir. Özel paywallınızı uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu kurulum, ürünlerinizi almanızı sağlar. Kontrol panelinde ne yapmanız gerektiğini anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetin \{#manage-users\} Kendi tarafınızda backend kimlik doğrulaması ile veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve tanımlanmış kullanıcıları farklı biçimde ele alır. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik belirleme hızlı başlangıç kılavuzunu](ios-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywall'ınız için ürünleri almak için şunları yapmanız gerekir: 1. [placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın. 2. Bu flow için ürünler dizisini `getPaywallProducts` metodunu kullanarak alın. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func loadPaywall() async { do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let products = try await Adapty.getPaywallProducts(flow: flow) // Use products to build your custom paywall UI } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func loadPaywall() { Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): Adapty.getPaywallProducts(flow: flow) { result in switch result { case let .success(products): // Use products to build your custom paywall UI case let .failure(error): // Handle the error } } case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\} Kullanıcı özel paywallınızdaki bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu, satın alma akışını yönetir ve güncellenmiş profili döndürür. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func purchaseProduct(_ product: AdaptyPaywallProduct) async { do { let purchaseResult = try await Adapty.makePurchase(product: product) switch purchaseResult { case .userCancelled: // User canceled the purchase break case .pending: // Purchase is pending (e.g., awaiting parental approval) break case let .success(profile, transaction): // Purchase successful, profile updated break } } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func purchaseProduct(_ product: AdaptyPaywallProduct) { Adapty.makePurchase(product: product) { result in switch result { case let .success(purchaseResult): switch purchaseResult { case .userCancelled: // User canceled the purchase break case .pending: // Purchase is pending (e.g., awaiting parental approval) break case let .success(profile, transaction): // Purchase successful, profile updated break } case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\} Apple, abonelik sunan tüm uygulamaların kullanıcıların satın almalarını geri yükleyebileceği bir yol sağlamasını zorunlu kılar. Satın almalar, kullanıcı Apple ID'siyle giriş yaptığında otomatik olarak geri yüklense de uygulamanızda yine de bir geri yükleme butonu eklemeniz gerekir. Kullanıcı geri yükleme butonuna dokunduğunda `restorePurchases` metodunu çağırın. Bu, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func restorePurchases() async { do { let profile = try await Adapty.restorePurchases() // Restore successful, profile updated } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func restorePurchases() { Adapty.restorePurchases { result in switch result { case let .success(profile): // Restore successful, profile updated case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywallınız uygulamada gösterilmeye hazır. Paywalldan bir test satın almasını tamamlayabildiğinizden emin olmak için [satın almalarınızı sandbox modunda test edin](test-purchases-in-sandbox). Ardından, paywallı gösterip göstermeyeceğinizi veya ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın almayı tamamlayıp tamamlamadığını kontrol edin](ios-check-subscription-status). --- # File: fetch-paywalls-and-products --- --- title: "iOS SDK'da remote config paywallları için paywall ve ürün çekme" description: "Kullanıcı monetizasyonunu artırmak için Adapty iOS SDK'da paywall ve ürünleri çekin." --- <SDKv4> Remote config ve özel paywallları uygulamanızda göstermeden önce, bunlara ait bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. **Flow Builder** veya **Paywall Builder** ile özelleştirilmiş flow'ları veya paywallları çekme rehberi için <InlineTooltip tooltip="uygulamanızda flow ve paywallları çekme rehberleri">[iOS](get-pb-paywalls), [Android](android-get-pb-paywalls), [React Native](react-native-get-pb-paywalls), [Flutter](flutter-get-pb-paywalls) ve [Unity](unity-get-pb-paywalls)</InlineTooltip> sayfalarına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow ya da paywall'ınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-ios). </details> ## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), App Store ve Google Play'den gelen ürünlerin bir kombinasyonudur. Bu çapraz platform ürünler, flow'lara ve paywall'lara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri görüntülemek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini koda sabit olarak yazmayın.** Koda sabit olarak yazmanız gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir flow bugün iki ürün döndürüyorsa yarın üç döndürebilir, tüm ürünleri kod değişikliği yapmadan göstermeniz gerekir. ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") // the requested flow } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın istikrarsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak amacıyla oturum boyunca kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, flow'ları ve paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Ayrıca flow'ları ve paywall'ları daha hızlı getirmek için CDN, CDN'e ulaşılamadığında ise bağımsız bir yedek sunucu kullanırız.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | :::note v4'te `locale` parametresi `getFlow`'dan çıkarılarak `getFlowConfiguration`'a taşındı (yalnızca AdaptyUI ile render edilirken kullanılır). Özel paywalllar için tüm mevcut locale'ler `flow.remoteConfigs` içinde birlikte döndürülür; kullanıcının cihazıyla veya uygulamanızın ayarıyla eşleşen locale'i seçin. ::: Ürün ID'lerini doğrudan koda yazmayın! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zamanla değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün gelirse, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Doğrudan koda yazmanız gereken tek şey placement ID'dir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, bir `remoteConfigs` dizisi (yapılandırılmış her locale için bir giriş) ve bir `hasViewConfiguration` bayrağı içeren `AdaptyFlow` nesnesi. Flow için ürünleri çekmek üzere `getPaywallProducts(flow:)` metodunu çağırın. | ## Ürünleri Getir \{#fetch-products\} Flow'u aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProducts(flow: flow) // the requested products array } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProducts(flow: flow) { result in switch result { case let .success(products): // the requested products array case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnelerinin listesi: ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler. | Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler açıklanmaktadır; tüm mevcut özellikler için bağlantılı belgeye bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin cihazın dilini değil, kullanıcının seçtiği mağaza ülkesini baz aldığını unutmayın. | | **Price** | Fiyatın yerelleştirilmiş sürümünü göstermek için `product.localizedPrice` kullanın. Bu yerelleştirme cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak `product.price` üzerinden de erişebilirsiniz. Değer yerel para biriminde verilir. İlgili para birimi sembolünü almak için `product.currencySymbol` kullanın. | | **Subscription Period** | Periyodu (hafta, ay, yıl vb.) göstermek için `product.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Abonelik periyoduna programatik olarak erişmek için `product.subscriptionPeriod` kullanın. Buradan süreyi almak için `unit` enum'una (gün, hafta, ay, yıl veya bilinmiyor) erişebilirsiniz. `numberOfUnits` değeri, periyot birimi sayısını verir. Örneğin üç aylık bir abonelik için unit özelliğinde `.month`, numberOfUnits'te ise `3` görürsünüz. | | **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionOffer` özelliğine bakın. Bu nesne aşağıdaki yararlı özellikleri içerir:<br/>• `offerType`: `introductory`, `promotional` ve `winBack` değerlerini alan bir enum. Ücretsiz denemeler ve başlangıç indirimli abonelikler `introductory` türündedir.<br/>• `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedPrice`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim fiyatı.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarıyla yerelleştirilmiş olarak açıklayan bir dize. Örneğin üç günlük deneme teklifi bu alanda `3 days` olarak görünür.<br/>• `subscriptionPeriod`: Teklif periyodunun ayrıntılarına bu özellik aracılığıyla da erişebilirsiniz; önceki bölümde açıklandığı gibi çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim abonelik periyodu. | :::note v4'te, `getPaywallProducts(flow:)` tarafından döndürülen tüm ürünler artık teklif uygunluk bilgisini içermektedir. v3'teki ayrı `getPaywallProductsWithoutDeterminingOffer` çağrısı kaldırılmıştır. ::: ## Varsayılan kitle flow'u ile flow getirme hızını artırın \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow'u getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi `getFlow` metoduyla flow'u getirmek olduğunu anlamak kritik önem taşır. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı flow'lar göstermeniz gerekiyorsa, bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görür; bu da ülkelere, pazarlama attribution verisine veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul edip daha hızlı flow getirme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") // the requested flow } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // istenen flow case let .failure(error): // hatayı işle } } ``` </TabItem> </Tabs> | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla sık karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerini azaltmak amacıyla oturum boyunca güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında korunduğunu, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p> | </SDKv4> <SDKv3> Remote config ve özel paywallları göstermeden önce, bunlarla ilgili bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllar ile ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları getirme konusunda rehberlik için <InlineTooltip tooltip="uygulamanızda Paywall Builder paywalllarını nasıl getireceğinize dair kılavuzlar">[iOS](get-pb-paywalls), [Android](android-get-pb-paywalls), [React Native](react-native-get-pb-paywalls), [Flutter](flutter-get-pb-paywalls) ve [Unity](unity-get-pb-paywalls)</InlineTooltip> sayfalarına bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall ve ürün çekmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri paywall'a ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-ios). </details> ## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'den ürünlerin birleşimini temsil eder. Bu çapraz platform ürünler, belirli mobil uygulama placement'larında gösterebilmek için paywallara entegre edilir. Ürünleri gösterebilmek için `getPaywall` metodunu kullanarak [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini koda gömmayın.** Koda gömmeniz gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak yönetebilmeli; bugün iki ürün döndüren bir paywall yarın üç ürün döndürüyorsa, kod değişikliğine gerek kalmadan hepsini göstermelidir. ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir; `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve kullanım önerileri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı çekmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanılır. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metod, işlem arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir.</p> | Ürün kimliklerini sabit kodlamayın! Paywall'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün getiriyorsanız, uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün getirirseniz, herhangi bir kod değişikliği gerektirmeksizin uygulamanız 3 ürünü de göstermelidir. Sabit kodlamanız gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'leri listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikler içeren bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywall'ı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProducts(paywall: paywall) // the requested products array } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProducts(paywall: paywall) { result in switch result { case let .success(products): // istenen ürünler dizisi case let .failure(error): // hatayı işle } } ``` </TabItem> </Tabs> Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler içeren [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirme, cihazın yerel ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapılır. | | **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.localizedPrice` kullanın. Bu yerelleştirme, cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak `product.price` üzerinden de erişebilirsiniz. Değer yerel para biriminde verilir. İlgili para birimi sembolünü almak için `product.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (örn. hafta, ay, yıl vb.) göstermek için `product.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme, cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionPeriod` kullanın. Buradan uzunluğu (gün, hafta, ay, yıl veya bilinmiyor) almak için `unit` enum'una erişebilirsiniz. `numberOfUnits` değeri, dönem birimlerinin sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `.month`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionOffer` özelliğine bakın. Bu nesne içinde aşağıdaki kullanışlı özellikler bulunur:<br/>• `offerType`: `introductory`, `promotional` ve `winBack` değerlerine sahip bir enum. Ücretsiz denemeler ve ilk indirimli abonelikler `introductory` türünde olur.<br/>• `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedPrice`: İndirimin kullanıcının yerel ayarına göre biçimlendirilmiş fiyatı.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarıyla açıklayan yerelleştirilmiş bir dize. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak görünür.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarını bu özellik aracılığıyla alabilirsiniz. Teklifler için bir önceki bölümde açıklanan şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: İndirimin abonelik döneminin kullanıcının yerel ayarına göre biçimlendirilmiş hali. | ## iOS'ta başlangıç teklifi uygunluğunu kontrol etme \{#check-intro-offer-eligibility-on-ios\} `getPaywallProducts` metodu varsayılan olarak başlangıç, promosyon ve geri kazanma teklifleri için uygunluğu kontrol eder. SDK teklif uygunluğunu belirlemeden önce ürünleri göstermeniz gerekiyorsa, bunun yerine `getPaywallProductsWithoutDeterminingOffer` metodunu kullanın. :::note İlk ürünleri gösterdikten sonra, ürünleri doğru teklif uygunluk bilgileriyle güncellemek için normal `getPaywallProducts` metodunu çağırmayı unutmayın. ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) // the requested products array without subscriptionOffer } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) { result in switch result { case let .success(products): // the requested products array without subscriptionOffer case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> ## Varsayılan kitle paywall'ı ile paywall çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Paywalllar genellikle neredeyse anında çekilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywall'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall çekme işlemi beklenenden daha uzun sürebilir. Böyle durumlarda hiç paywall göstermemek yerine kullanıcı deneyimini sorunsuz tutmak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bu sorunu çözmek için **All Users** kitlesine ait belirtilen placement'ın paywall'ını çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metodunu kullanmak olduğunu bilmeniz önemlidir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun bazı önemli dezavantajları vardır: - **Geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların düzgün render edilemeyen paywalllarla karşılaşabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da ülkeye, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı paywall çekme avantajından yararlanmak istiyorsanız `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanabilirsiniz. Aksi hâlde [yukarıda](fetch-paywalls-and-products#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> :::note `getPaywallForDefaultAudience` metodu iOS SDK 2.11.2 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirme](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.</p><p></p><p>Yerel ayar kodları ve kullanım önerileri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği kullanmanızı öneririz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşar. Önbellek düzenli olarak güncellenir, bu nedenle oturum boyunca gereksiz ağ isteklerini önlemek amacıyla güvenle kullanılabilir.</p><p></p><p>Önbellek, uygulama yeniden başlatıldığında korunur; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlanır.</p> | </SDKv3> --- # File: present-remote-config-paywalls --- --- title: "iOS SDK'da remote config ile tasarlanan paywall'u render etme" description: "Kullanıcı deneyimini kişiselleştirmek için Adapty'de remote config paywall'larının nasıl sunulacağını keşfedin." --- <SDKv4> Remote config ile bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulama kodunuzda render işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini siz belirlersiniz. Adapty, remote config'i çekmeniz için bir metot sunar; özel paywall'ınızı nasıl göstereceğiniz tamamen size kalmıştır. [iOS'ta kullanıcının başlangıç teklifine uygun olup olmadığını kontrol etmeyi](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) ve paywall görünümünü bu duruma göre ayarlamayı unutmayın. ## Flow remote config'ini alın ve sunun \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` dizisinde yapılandırılmış her locale için bir `AdaptyRemoteConfig` girişi taşır. Kullanıcının tercihiyle eşleşen locale'i seçin, ardından ihtiyaç duyduğunuz değerleri okuyun. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let config = flow.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow.remoteConfigs.first let headerText = config?.dictionary?["header_text"] as? String } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in let flow = try? result.get() let config = flow?.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow?.remoteConfigs.first let headerText = config?.dictionary?["header_text"] as? String } ``` </TabItem> </Tabs> Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel olarak çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olarak tüm cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunun. :::warning Adapty analitiğinin huni ve A/B testi bilgilerini yakalayabilmesi için aşağıda açıklandığı şekilde [paywall görüntüleme etkinliğini kaydettiğinizden](present-remote-config-paywalls#track-paywall-view-events) emin olun. ::: Paywwall'ı görüntüledikten sonra, satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılar için [Satın alma yapma](making-purchases) bölümünü okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme olaylarını takip etme \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da, paywall görüntüleme olaylarını kaydetmek sizin müdahalenizi gerektiriyor; çünkü bir müşterinin paywall'ı ne zaman gördüğünü yalnızca siz biliyorsunuz. Paywall görüntüleme olayını kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterli. Bu işlem, funnel'lar ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülüyorsanız `.logShowFlow(flow)` çağrısına gerek yoktur. Adapty bu durumlarda görüntülemeleri otomatik olarak takip eder. ::: ```swift showLineNumbers try await Adapty.logShowFlow(flow) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :-------- | :------- |:-----------------------------------------------------------------------------------------| | **flow** | zorunlu | `Adapty.getFlow(placementId:)` ile elde edilen bir `AdaptyFlow` nesnesi. | </SDKv4> <SDKv3> Remote config kullanarak bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywallınıza nelerin dahil edileceğini ve nasıl görüneceğini siz belirlersiniz. Remote config aracılığıyla yapılandırılan özel paywallınızı göstermek için remote config'i çekmenizi sağlayan bir metot sunuyoruz. [iOS'ta kullanıcının başlangıç teklifine uygun olup olmadığını kontrol etmeyi](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) ve uygun olduğu durumu işlemek için paywall görünümünü ayarlamayı unutmayın. ## Paywall remote config'ini alma ve sunma \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri çıkarın. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") let headerText = paywall.remoteConfig?.dictionary?["header_text"] as? String } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") { result in let paywall = try? result.get() let headerText = paywall?.remoteConfig?.dictionary?["header_text"] as? String } ``` </TabItem> </Tabs> Bu noktada gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiş demektir. Tasarımın farklı mobil ekran boyutlarına ve yönlendirmelerine uyum sağladığından, çeşitli cihazlarda kesintisiz ve kullanıcı dostu bir deneyim sunduğundan emin olun. :::warning Adapty analitiğinin dönüşüm hunileri ve A/B testleri için bilgi toplayabilmesi amacıyla aşağıda açıklandığı gibi [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls#track-paywall-view-events) emin olun. ::: Paywallı göstermeyi tamamladıktan sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](making-purchases) bölümüne bakın. Yedek paywall olarak adlandırılan [bir yedek paywall oluşturmanızı](fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir; böylece bu durumlarda bile sorunsuz bir deneyim sağlanır. ## Paywall görüntüleme olaylarını takip etme \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplarken, paywall görüntülemelerini kayıt altına almak sizin müdahalenizi gerektirir; çünkü bir müşterinin paywall'ı ne zaman gördüğünü yalnızca siz bilirsiniz. Bir paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu işlem, funnel'lardaki ve A/B testlerindeki paywall metriklerinize yansıyacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywall'ları gösteriyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```swift showLineNumbers Adapty.logShowPaywall(paywall) ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:--------------------------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. | </SDKv3> --- # File: making-purchases --- --- title: "iOS SDK'da mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın alma ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'ları göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, bu paywall'ları görüntülemek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime girmesini ve istedikleri işlemleri gerçekleştirmesini sağlar. Paywall'ınızda kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa, Adapty bunu satın alma anında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın. Diğer durumlarda, [iOS'ta kullanıcının başlangıç teklifine uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlamak uygulamanızın yayın sırasında reddedilmesine yol açabilir. Üstelik, başlangıç teklifine hak kazanan kullanıcıların tam fiyat ödenmesine neden olabilir. ::: Tek bir adımı bile atlamadan [başlangıç yapılandırmasını](quickstart) tamamladığınızdan emin olun. Bu yapılmadan satın almaları doğrulayamayız. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir—bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlamlı uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](ios-implement-paywalls-manually) bakın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let purchaseResult = try await Adapty.makePurchase(product: product) switch purchaseResult { case .userCancelled: // Handle the case where the user canceled the purchase case .pending: // Handle deferred purchases (e.g., the user will pay offline with cash) case let .success(profile, transaction): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // Grant access to the paid features } } } catch { // Handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.makePurchase(product: product) { result in switch result { case let .success(purchaseResult): switch purchaseResult { case .userCancelled: // Handle the case where the user canceled the purchase case .pending: // Handle deferred purchases (e.g., the user will pay offline with cash) case let .success(profile, transaction): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // Grant access to the paid features } } case let .failure(error): // Handle the error } } ``` </TabItem> </Tabs> İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- | :----------------------------------------------------------------------------------------------- | | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>İstek başarılıysa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi, kullanıcının uygulamadaki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.</p><p>Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.</p> | :::warning **Not:** Hâlâ Apple'ın StoreKit sürüm 2.0'ın altında ve Adapty SDK sürüm 2.9.0'ın altında bir sürüm kullanıyorsanız, bunun yerine [Apple App Store paylaşılan secret anahtarını](app-store-connection-configuration#step-5-enter-app-store-shared-secret) girmeniz gerekir. Bu yöntem Apple tarafından artık kullanımdan kaldırılmıştır. ::: ## App Store'dan uygulama içi satın almalar \{#in-app-purchases-from-the-app-store\} Bir kullanıcı App Store'da satın alma başlattığında ve işlem uygulamanıza taşındığında iki seçeneğiniz vardır: - **İşlemi hemen gerçekleştirin:** `shouldAddStorePayment` içinde `true` döndürün. Bu, Apple satın alma sistem ekranını hemen gösterir. - **Ürün nesnesini sonraki işlem için saklayın:** `shouldAddStorePayment` içinde `false` döndürün, ardından saklanan ürünle `makePurchase`'i daha sonra çağırın. Bu, satın almayı tetiklemeden önce kullanıcıya özel bir şey göstermeniz gerektiğinde işe yarar. Tam kod parçacığı şöyle: ```swift showLineNumbers title="Swift" final class YourAdaptyDelegateImplementation: AdaptyDelegate { nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool { // 1a. // Return `true` to continue the transaction in your app. The Apple purchase system screen will show automatically. // 1b. // Store the product object and return `false` to defer or cancel the transaction. false } // 2. Continue the deferred purchase later on by passing the product to `makePurchase` when the timing is appropriate func continueDeferredPurchase() async { let storedProduct: AdaptyDeferredProduct = // get the product object from 1b. do { try await Adapty.makePurchase(product: storedProduct) } catch { // handle the error } } } ``` ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanım sayfasını göstermek için: ```swift showLineNumbers Adapty.presentCodeRedemptionSheet() ``` :::danger Gözlemlerimize göre bazı uygulamalarda Teklif Kodu Kullanım sayfası güvenilir şekilde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için şu formattaki URL'yi açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: --- # File: restore-purchase --- --- title: "iOS SDK'da mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz kullanıcı deneyimi sağlamak için Adapty'de satın almaları nasıl geri yükleyeceğinizi öğrenin." --- Satın Almaları Geri Yükleme, kullanıcıların daha önce satın aldıkları içeriklere (abonelikler veya uygulama içi satın almalar gibi) tekrar ücret ödemeden yeniden erişmesini sağlayan bir özelliktir. Bu özellik, özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça faydalıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywall'larda satın almalar, sizin tarafınızdan herhangi bir ek kod yazılmadan otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz. ::: Paywall'ı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almayı geri yüklemek için `.restorePurchases()` metodunu çağırın: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.restorePurchases() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // successful access restore } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.restorePurchases { [weak self] result in switch result { case let .success(profile): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // successful access restore } case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> Yanıt parametreleri: | Parametre | Açıklama | |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>Bir [`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi. Bu model, access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir.</p><p>Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.</p> | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: ios-transaction-management --- --- title: "iOS SDK'da gelişmiş işlem yönetimi" description: "Adapty SDK ile iOS uygulamanızda işlemleri manuel olarak tamamlayın." --- :::note Gelişmiş işlem yönetimi, Adapty iOS SDK'nın 3.12 sürümünden itibaren desteklenmektedir. ::: Adapty'deki gelişmiş işlem yönetimi, işlemlerin nasıl ele alındığı, doğrulandığı ve tamamlandığı üzerinde size daha fazla kontrol sağlar. Gelişmiş işlem yönetimi, birlikte çalışan üç isteğe bağlı özellik sunar: | Özellik | Amaç | |-------------------------------------------------------------|----------| | [`appAccountToken`](#assign-appaccounttoken) | Apple işlemlerini dahili kullanıcı kimliğinize bağlar | | [`jwsTransaction`](#access-the-jws-representation) | Doğrulama için Apple'ın imzalanmış işlem yükünü sağlar | | [Manuel tamamlama](#control-transaction-finishing-behavior) | İşlemleri yalnızca backend'iniz başarıyı onayladıktan sonra tamamlamanıza olanak tanır | Bu araçlar birlikte, Adapty işlemleri kendi backend'iyle senkronize etmeye devam ederken sağlam özel doğrulama akışları oluşturmanıza imkân verir. :::important Çoğu uygulamanın buna ihtiyacı yoktur. Varsayılan olarak Adapty, StoreKit işlemlerini otomatik olarak doğrular ve tamamlar. Bu kılavuzu yalnızca kendi backend doğrulamanızı çalıştırıyorsanız veya satın alma yaşam döngüsünü tamamen kontrol etmek istiyorsanız kullanın. ::: ## `appAccountToken` atama \{#assign-appaccounttoken\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinize bağlamanızı sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle ilişkilendirir; böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulan kararlı bir UUID kullanın ve aynı hesap için farklı cihazlarda da bu UUID'yi yeniden kullanın. Bu, satın almaların ve App Store bildirimlerinin doğru şekilde eşleştirilmesini sağlar. Token'ı iki farklı şekilde ayarlayabilirsiniz: SDK etkinleştirmesi sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmeniz gerekir. Yalnızca token'ı geçerseniz işleme dahil edilmez. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } // Or when identifying a user: do { try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: <APP_ACCOUNT_TOKEN>) Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } // Or when identifying a user: Adapty.identify("YOUR_USER_ID", withAppAccountToken: <APP_ACCOUNT_TOKEN>) { error in if let error { // handle the error } } ``` </TabItem> </Tabs> ## JWS gösterimine erişme \{#access-the-jws-representation\} Bir satın alma yaptığınızda, sonuç Apple'ın işlemini [JWS Compact Serialization formatında](https://developer.apple.com/documentation/storekit/verificationresult/jwsrepresentation-21vgo) içerir. Bu değeri bağımsız doğrulama veya kayıt amacıyla backend'inize iletebilirsiniz. ```swift let result = try await Adapty.makePurchase(product: paywallProduct) let jwsRepresentation = result.jwsTransaction ``` ## İşlem tamamlama davranışını kontrol etme \{#control-transaction-finishing-behavior\} Varsayılan olarak Adapty, StoreKit işlemlerini doğrulamanın ardından otomatik olarak tamamlar. Backend'inizin başarıyı onaylamasına kadar tamamlamayı ertelemek istiyorsanız tamamlama davranışını manuel olarak ayarlayın. Bu modda: - Adapty yine de satın almaları doğrular ve kendi backend'iyle senkronize eder. - `finish()` metodunu açıkça çağırana kadar işlemler tamamlanmamış olarak kalır. ```swift var configBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_API_KEY") .with(transactionFinishBehavior: .manual) try await Adapty.activate(with: configBuilder.build()) ``` Manuel işlem tamamlamayı kullanırken, tamamlanmamış işlemleri yönetmek için `onUnfinishedTransaction` delegate metodunu uygulamanız gerekir: ```swift showLineNumbers title="Swift" extension YourApp: AdaptyDelegate { func onUnfinishedTransaction(_ transaction: AdaptyUnfinishedTransaction) async { // Perform your custom validation logic here // When ready, finish the transaction await transaction.finish() } } ``` Mevcut tüm tamamlanmamış işlemleri almak için `getUnfinishedTransactions()` metodunu kullanın: ```swift let unfinishedTransactions = try await Adapty.getUnfinishedTransactions() ``` --- # File: implement-observer-mode --- --- title: "iOS SDK'da Observer modu uygulama" description: "iOS SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve henüz tamamen Adapty'ye geçmeye hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer Modu, gelişmiş analitik ile attribution ve analitik sistemleriyle sorunsuz entegrasyon sunar. Bu sizin ihtiyaçlarınızı karşılıyorsa yalnızca şunları yapmanız gerekir: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak Observer modunu etkinleştirin. 2. Mevcut satın alma altyapınızdaki işlemleri Adapty'ye [bildirin](report-transactions-observer-mode). Paywall'lar ve A/B testi de kullanmak istiyorsanız, aşağıda açıklandığı gibi ek kurulum adımları gereklidir. ## Observer modu kurulumu \{#observer-mode-setup\} Satın alma işlemlerini ve abonelik durumunu kendiniz yönetip abonelik olayları ile analitik göndermek için Adapty kullanıyorsanız Observer modunu etkinleştirin. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle bunu kendiniz yönettiğinizden emin olun. ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers @main struct YourApp: App { init() { // Configure Adapty SDK let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(observerMode: true) let config = configurationBuilder.build() // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: configurationBuilder) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } var body: some Scene { WindowGroup { // Your content view } } } } ``` </TabItem> <TabItem value="swift" label="UIKit" default> ```swift showLineNumbers Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(observerMode: true) let config = configurationBuilder.build() try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden boolean değer. Varsayılan değer `false`'tur. | ## Observer Modunda Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz — ancak Observer modunda bazı ek kurulum adımları gereklidir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir: 1. [Remote config paywall'ları](present-remote-config-paywalls) için paywall'ları normalde olduğu gibi gösterin. Paywall Builder paywall'ları için [iOS](ios-present-paywall-builder-paywalls-in-observer-mode)'a özel kurulum kılavuzunu izleyin. 3. Paywall'ları satın alma işlemleriyle [ilişkilendirin](report-transactions-observer-mode). --- # File: report-transactions-observer-mode --- --- title: "iOS SDK'da Observer Mode'da işlemleri bildirme" description: "iOS SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini bildirin." --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+ (güncel)" default> Observer Mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. App Store'dan gelen işlemleri manuel olarak bildirmeniz gerekir. Analizlerde hata oluşmaması için uygulamanızı yayınlamadan **önce** bu adımı tamamlamanız çok önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanın. :::warning **İşlem bildirmeyi atlamayın!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywalllarını kullanıyorsanız, işlemi bildirirken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywalla bağlar ve paywall analizlerinin doğru çalışmasını sağlar. ```swift showLineNumbers do { // every time when calling transasction.finish() try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) } catch { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | --------------------------------------------------------- | | **transaction** | zorunlu | <ul><li> StoreKit 1 için: SKPaymentTransaction.</li><li> StoreKit 2 için: Transaction.</li></ul> | | **variationId** | isteğe bağlı | Paywall varyantının benzersiz kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğinden alabilirsiniz. | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x (eski)" default> Observer Mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. App Store'dan gelen işlemleri bildirmeniz veya geri yüklemeniz gerekir. Analizlerde hata oluşmaması için uygulamanızı yayınlamadan **önce** bu adımı tamamlamanız çok önemlidir. İşlem verilerini Adapty'ye göndermek için `reportTransaction` kullanın. :::warning **İşlem bildirmeyi atlamayın!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywalllarını kullanıyorsanız, işlemi bildirirken `withVariationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywalla bağlar ve paywall analizlerinin doğru çalışmasını sağlar. ```swift showLineNumbers do { // every time when calling transasction.finish() try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) } catch { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | ---------- | --------------------------------------------------------- | | **transaction** | zorunlu | <ul><li> StoreKit 1 için: SKPaymentTransaction.</li><li> StoreKit 2 için: Transaction.</li></ul> | | **variationId** | isteğe bağlı | Paywall varyantının benzersiz kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğinden alabilirsiniz. | </TabItem> <TabItem value="old2" label="Adapty SDK 3.2.x ve öncesi (eski)" default> **İşlemleri bildirme** - 3.1.x ve önceki sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel bildirim gerekmez. - 3.2 sürümü Observer Mode'u desteklemiyor. **Paywallları işlemlerle ilişkilendirme** Adapty SDK, satın almaları siz işlediğiniz için bunların kaynağını belirleyemez. Bu nedenle Observer Mode'da paywall ve/veya A/B testi kullanmak istiyorsanız, mobil uygulama kodunuzda App Store'dan gelen işlemi ilgili paywalla bağlamanız gerekir. Bu adımı uygulamanızı yayınlamadan önce doğru şekilde yapmazsanız analizlerde hatalara yol açar. ```swift let variationId = paywall.variationId // There are two overloads: for StoreKit 1 and StoreKit 2 Adapty.setVariationId(variationId, forPurchasedTransaction: transactionId) { error in if error == nil { // successful binding } } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | --------------------------------------------------------- | | variationId | zorunlu | Varyantın string kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. | | transactionId | zorunlu | <p>StoreKit 1 için: [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</p><p>StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</p> | </TabItem> </Tabs> --- # File: ios-troubleshoot-purchases --- --- title: "iOS SDK'da satın alma sorunlarını giderme" description: "iOS SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, iOS SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyelrorrcantmakepayments-in-observer-mode\} **Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmalısınız ya da observer modunda satın almaları kendi tarafınızda yönetmelisiniz. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode) sayfasına bakın. ## makePurchasesCompletionHandlers bulunamıyor \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamadığına dair sorunlarla karşılaşıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu yöntem, sandbox ile ilgili satın alma tamamlama işleyicisi sorunlarını çoğu zaman çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekiyorsa [migration kılavuzlarını](ios-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüş durumdadır. --- # File: ios-web-paywall --- --- title: "iOS SDK'da web paywalllarını uygulama" description: "App Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall kurun." --- :::important Başlamadan önce [kontrol panelinde web paywallınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya sonraki bir sürümünü yüklediğinizden emin olun. ::: ## Web paywalllarını açma \{#open-web-paywalls\} Kendiniz geliştirdiğiniz bir paywall üzerinde çalışıyorsanız, web paywalllarını SDK metodu aracılığıyla ele almanız gerekir. `.openWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywallı yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü izler ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` isteği gönderir. Bu sayede ödeme başarılı olup erişim hakları güncellendiğinde, abonelik uygulamada neredeyse anında etkinleşir. ```swift showLineNumbers title="Swift" do { try await Adapty.openWebPaywall(for: product) } catch { print("Failed to open web paywall: \(error)") } ``` :::note `openWebPaywall` metodunun iki versiyonu vardır: 1. `openWebPaywall(product)`: URL'leri paywalla göre oluşturur ve ürün verilerini de URL'lere ekler. 2. `openWebPaywall(paywall)`: URL'leri paywalla göre oluşturur ancak ürün verilerini eklemez. Adapty paywallındaki ürünler web paywallındakilerden farklı olduğunda bunu kullanın. ::: ## Hataları ele alma \{#handle-errors\} | Hata | Açıklama | Önerilen işlem | |-----------------------------------------|------------------------------------------------------------|-----------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Paywall için web satın alma URL'si yapılandırılmamış | Paywallın Adapty Kontrol Paneli'nde doğru şekilde yapılandırılıp yapılandırılmadığını kontrol edin | | AdaptyError.productWithoutPurchaseUrl | Ürünün web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın | | AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun | | AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler düzgün şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimde olduğunu doğrulayın | ## Uygulama örneği \{#implementation-example\} ```swift showLineNumbers title="Swift" class SubscriptionViewController: UIViewController { var paywall: AdaptyPaywall? @IBAction func purchaseButtonTapped(_ sender: UIButton) { guard let paywall = paywall, let product = paywall.products.first else { return } Task { await offerWebPurchase(for: product) } } func offerWebPurchase(for paywallProduct: AdaptyPaywallProduct) async { do { // Attempt to open web paywall try await Adapty.openWebPaywall(for: paywallProduct) } catch let error as AdaptyError { switch error { case .paywallWithoutPurchaseUrl, .productWithoutPurchaseUrl: showAlert(message: "Web purchase is not available for this product.") case .failedOpeningWebPaywallUrl: showAlert(message: "Could not open web browser. Please try again.") default: showAlert(message: "An error occurred: \(error.localizedDescription)") } } catch { showAlert(message: "An unexpected error occurred.") } } // Helper methods private func showAlert(message: String) { /* ... */ } } ``` :::note Kullanıcılar uygulamaya döndükten sonra, profil güncellemelerini yansıtmak için arayüzü yenileyin. `AdaptyDelegate`, profil güncelleme olaylarını alıp işleyecektir. ::: ## Web paywallları uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywalllarını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Web paywalllar varsayılan olarak harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sunmak için web paywalllarını uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanız içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `in` parametresini `.inAppBrowser` olarak ayarlayın: ```swift showLineNumbers title="Swift" do { try await Adapty.openWebPaywall(for: product, in: .inAppBrowser) // default – .externalBrowser } catch { print("Failed to open web paywall: \(error)") } ``` --- # File: identifying-users --- --- title: "iOS SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini iyileştirmek için Adapty'de kullanıcıları tanımlayın." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamanız gerekir. Kullanıcıları Customer User ID'leriyle [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [server-side API](getting-started-with-server-side-api)'de kullanabilirsiniz. ## Yapılandırma sırasında customer user ID'yi ayarlama \{#set-customer-user-id-on-configuration\} Yapılandırma sırasında kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçmeniz yeterlidir: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` </TabItem> </Tabs> :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Yapılandırma sonrasında customer user ID'yi ayarlama \{#set-customer-user-id-after-configuration\} SDK yapılandırması sırasında kullanıcı ID'niz yoksa, istediğiniz zaman `.identify()` metoduyla sonradan ayarlayabilirsiniz. Bu metodun en yaygın kullanım durumları, kayıt veya giriş sonrasında kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçişidir. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> </Tabs> İstek parametreleri: - **Customer User ID** (zorunlu): Bir string kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahip olabilir. Bu senaryolarda Adapty SDK'sı otomatik olarak yeni kullanıcıyla çalışmaya geçer. Anonim kullanıcıya özel özellikler veya üçüncü taraf ağlardan attribution verileri gibi herhangi bir veri aktardıysanız, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden talep etmeniz gerektiğini unutmayın. ::: ## Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak istediğiniz zaman kullanıcının oturumunu kapatabilirsiniz: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.logout() } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.logout { error in if error == nil { // successful logout } } ``` </TabItem> </Tabs> Ardından `.identify()` metodunu kullanarak kullanıcının oturumunu açabilirsiniz. ## appAccountToken'ı ayarlama \{#set-appaccounttoken\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), Apple'ın StoreKit 2'nin kullanıcıları uygulama yüklemeleri ve cihazlar genelinde tanımlamasına yardımcı olan bir UUID'dir. Adapty iOS SDK 3.10.2 sürümünden itibaren, SDK'yı yapılandırırken veya bir kullanıcıyı tanımlarken `appAccountToken` değerini geçebilirsiniz: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } // Or when identifying a user: do { try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } // Or when identifying a user: Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) { error in if let error { // handle the error } } ``` </TabItem> </Tabs> Ardından `.identify()` metodunu kullanarak kullanıcının oturumunu açabilirsiniz. ## Cihazlar Arası Kullanıcı Tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: setting-user-attributes --- --- title: "iOS SDK'da kullanıcı özelliklerini ayarlama" description: "Daha iyi kitle segmentasyonu için Adapty'de kullanıcı özelliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulamanızın kullanıcılarına e-posta, telefon numarası gibi isteğe bağlı özellikler ekleyebilirsiniz. Bu özellikleri kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz. ### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(email: "email@email.com") .with(phoneNumber: "+18888888888") .with(firstName: "John") .with(lastName: "Appleseed") .with(gender: .other) .with(birthday: Date()) do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(email: "email@email.com") .with(phoneNumber: "+18888888888") .with(firstName: "John") .with(lastName: "Appleseed") .with(gender: .other) .with(birthday: Date()) Adapty.updateProfile(params: builder.build()) { error in if error != nil { // handle the error } } ``` </TabItem> </Tabs> `updateProfile` metoduyla daha önce ayarladığınız özellikler sıfırlanmaz. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen anahtarlar `<Key>` ve değerler `<Value>` aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı özellikleri \{#custom-user-attributes\} Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin; fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi düzeyi gibi. Bu özellikleri, hedefli paywall'lar ve teklifler oluşturmak için segmentlerde; hangi ürün metriklerinin geliri en çok etkilediğini anlamak için de analitikte kullanabilirsiniz. ```swift showLineNumbers do { builder = try builder.with(customAttribute: "value1", forKey: "key1") } catch { // handle key/value validation error } ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```swift showLineNumbers do { builder = try builder.withRemoved(customAttributeForKey: "key2") } catch { // handle error } ``` Bazen daha önce hangi özel özelliklerin ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı özellikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, sunucudaki özellikler son senkronizasyondan bu yana değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel özellik - Anahtar adları en fazla 30 karakter olabilir. Anahtar adı alfanümerik karakterler ve şu karakterlerden herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakter uzunluğunda bir string veya float olabilir. --- # File: subscription-status --- --- title: "iOS SDK'da abonelik durumunu kontrol etme" description: "Müşteri tutunumunu artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek çok kolaydır. Ürün kimliklerini kodunuza elle girmenize gerek yoktur. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. Abonelik durumunu kontrol etmeye başlamadan önce [App Store Server Notifications](enable-app-store-server-notifications) ayarlarını yapın. ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesinin özelliklerdir. Profili; uygulamanız başladığında, örneğin [bir kullanıcıyı tanımladığınızda](identifying-users#set-customer-user-id-on-configuration), alıp değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini defalarca istek atmadan kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için, aşağıdaki [Abonelik durumu güncellemelerini dinleme](subscription-status#listening-for-subscription-status-updates) bölümünde açıklandığı gibi profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Access level'ı sunucudan alma \{#retrieving-the-access-level-from-the-server\} Access level'ı sunucudan almak için `.getProfile()` metodunu kullanın: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> </Tabs> Yanıt parametreleri: | Parametre | Açıklama | | --------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile | <p>Bir [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi. Genel olarak, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.</p><p></p><p>`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (ör. internet bağlantısı yoksa) Adapty SDK sunucudan bilgi alamazsa, önbelleğe alınmış veriler döndürülür. Ayrıca Adapty SDK, `AdaptyProfile` önbelleğini düzenli aralıklarla güncelleyerek bu bilgilerin mümkün olduğunca güncel kalmasını sağlar.</p> | `.getProfile()` metodu size kullanıcı profilini döndürür; bu profil üzerinden access level durumunu öğrenebilirsiniz. Bir uygulamada birden fazla access level tanımlayabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız "sports" ve "science" adında access level'lar oluşturabilirsiniz. Ancak çoğu zaman yalnızca bir access level'a ihtiyaç duyarsınız; böyle durumlarda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() let isPremium = profile.accessLevels["premium"]?.isActive ?? false // grant access to premium features } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get(), profile.accessLevels["premium"]?.isActive ?? false { // grant access to premium features } } ``` </TabItem> </Tabs> ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir: ```swift showLineNumbers Adapty.delegate = self // To receive subscription updates, extend `AdaptyDelegate` with this method: nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { // handle any changes to subscription state } ``` Adapty, uygulama başlangıcında da bir olay tetikler. Bu durumda önbelleğe alınmış abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucuya erişilemese bile önbelleğe alınan veriler kullanılarak profil abonelik durumu hakkında bilgi edinilebilir. Ancak önbellekten doğrudan veri isteği yapılamayacağını belirtmek gerekir. SDK, profilde herhangi bir güncelleme veya değişiklik olup olmadığını kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler varsa, bunlar sunucuyla senkronize kalması için önbelleğe alınan verilere yansıtılır. --- # File: ios-deal-with-att --- --- title: "iOS SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumunu ve yönetimini kolaylaştırmak için iOS'ta Adapty'yi kullanmaya başlayın." --- Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama izleme yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(appTrackingTransparencyStatus: .authorized) do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers if #available(iOS 14, macOS 11.0, *) { let builder = AdaptyProfileParameters.Builder() .with(appTrackingTransparencyStatus: .authorized) Adapty.updateProfile(params: builder.build()) { [weak self] error in if error != nil { // handle the error } } } ``` </TabItem> </Tabs> :::warning Bu değeri değiştiği anda mümkün olan en kısa sürede göndermenizi şiddetle tavsiye ederiz; yalnızca bu durumda veriler, yapılandırdığınız entegrasyonlara zamanında iletilir. ::: --- # File: kids-mode --- --- title: "iOS SDK'da Çocuk Modu" description: "Apple politikalarına uymak için Çocuk Modunu kolayca etkinleştirin. iOS SDK'da IDFA veya reklam verisi toplanmaz." --- <SDKv4> iOS uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikalara uygun şekilde yapılandırabilir ve uygulama mağazası incelemelerinden geçebilirsiniz. ## Neler gerekli? \{#whats-required\} Aşağıdaki verilerin toplanmasını devre dışı bırakmak için Adapty SDK'yı yapılandırmanız gerekir: - [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Ayrıca müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `<FirstName.LastName>` formatındaki kullanıcı kimliği, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilecektir. Çocuk Modu için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (ör. hash'lenmiş kimlikler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Kids Modunu Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'ndeki Güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekiyor. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzdaki güncellemeler \{#updates-in-your-mobile-app-code\} SDK 4.0 ile birlikte Kids Mode, `KidsMode` adında bir Swift package trait'idir. Bu trait etkinleştirildiğinde, IDFA ve AdSupport tüm SDK genelinde derleme aşamasında devre dışı bırakılır; normal **Adapty** ve **AdaptyUI** modüllerini ve `import Adapty` / `import AdaptyUI` ifadelerini kullanmaya devam edersiniz. :::note `KidsMode` trait'i SDK 4.0 sürümünden itibaren kullanılabilir. SDK 4.0'dan itibaren SDK yalnızca Swift Package Manager aracılığıyla kurulmaktadır — CocoaPods artık desteklenmemektedir. ::: <Tabs> <TabItem value="xcode" label="Xcode" default> 1. [Adapty SDK'yı](sdk-installation-ios) her zamanki gibi yükleyin; standart **Adapty** ve **AdaptyUI** modüllerini seçin. 2. Xcode 26.4 veya sonraki sürümlerde proje ayarlarınızı açın, **Package Dependencies** görünümüne gidin ve AdaptySDK-iOS bağımlılığı için **KidsMode** trait'ini etkinleştirin. :::note Xcode 26.4'ten önceki sürümler, bir Xcode projesinde kullanıcı arayüzü üzerinden trait'leri etkinleştiremez. Bu durumda, `KidsMode` trait'i etkinleştirilmiş şekilde Adapty'ye bağımlı küçük bir yerel Swift paketi oluşturun (**Package.swift** sekmesine bakın) ve uygulama hedefinizi bu pakete bağımlı yapın. ::: </TabItem> <TabItem value="spm" label="Package.swift"> Adapty'yi `Package.swift` dosyasında bağımlılık olarak ekliyorsanız, trait'i paket bildiriminde etkinleştirin. Trait'ler için `swift-tools-version` 6.1 veya üstü gereklidir. ```swift showLineNumbers title="Package.swift" .package( url: "https://github.com/adaptyteam/AdaptySDK-iOS.git", from: "4.0.0", traits: ["KidsMode"] ) ``` </TabItem> </Tabs> </SDKv4> <SDKv3> iOS uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla bu politikaları karşılayacak şekilde yapılandırabilir ve uygulama mağazası incelemelerinden geçebilirsiniz. ## Neler gerekli? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Ayrıca, müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `<FirstName.LastName>` biçimindeki kullanıcı kimliği, e-posta kullanımında olduğu gibi kişisel veri toplama olarak değerlendirilecektir. Çocuk Modu için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (örneğin, karma kimlikler veya cihaz tarafından üretilen UUID'ler) kullanmaktır. ## Çocuk Modunu Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde Yapılacak Güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplama özelliğini devre dışı bırakmanız gerekiyor. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için kullanıcının IDFA'sı ve IP adresi toplanmasını devre dışı bırakın. <Tabs> <TabItem value="spm" label="Swift Package Manager" default> Swift Package Manager kullanıyorsanız, SDK'yı yüklerken Xcode'da **Adapty_KidsMode** modülünü seçerek Kids Mode'u etkinleştirebilirsiniz. Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme adımları Xcode sürümleri arasında farklılık gösterebileceğinden, gerekirse Xcode belgelerine başvurun. 1. Depo URL'sini girin: ``` https://github.com/adaptyteam/AdaptySDK-iOS.git ``` 2. Sürümü seçin (en son kararlı sürüm önerilir) ve **Add Package** düğmesine tıklayın. 3. **Choose Package Products** penceresinde ihtiyacınız olan modülleri seçin: - **Adapty_KidsMode** (çekirdek modül) - **AdaptyUI_KidsMode** (isteğe bağlı - yalnızca Paywall Builder kullanmayı planlıyorsanız) Başka paketlere ihtiyacınız olmayacak. 4. Kurulumu tamamlamak için **Add Package** düğmesine tıklayın. 5. Kodunuzda `import Adapty` yerine `import Adapty_KidsMode`, `import AdaptyUI` yerine `import AdaptyUI_KidsMode` yazın: ```swift ``` </TabItem> <TabItem value="cocoapods" label="CocoaPods"> 1. Podfile dosyanızı güncelleyin: - Eğer `post_install` bölümünüz **yoksa**, aşağıdaki kod bloğunun tamamını ekleyin. - Eğer `post_install` bölümünüz **varsa**, vurgulanan satırları mevcut bölümle birleştirin. ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. Değişiklikleri uygulamak için aşağıdaki komutu çalıştırın: ```sh showLineNumbers title="Shell" pod install ``` </TabItem> </Tabs> </SDKv3> --- # File: get-onboardings --- --- title: "Onboarding'leri ve yapılandırmalarını getir" description: "Adapty'de onboarding'leri nasıl alacağınızı öğrenin." --- :::tip **SDK v4 itibarıyla**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda nativ olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow'ları ve paywall'ları alma](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) sayfalarına bakın. ::: [Adapty Kontrol Paneli'ndeki builder ile onboarding'inizin görsel kısmını tasarladıktan](design-onboarding) sonra, bunu mobil uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır. Başlamadan önce şunları kontrol edin: 1. [Adapty iOS, Android, React Native veya Flutter SDK](installation-of-adapty-sdks) sürüm 3.8.0 veya üzerini yüklemiş olmanız gerekir. 2. [Bir onboarding oluşturmuş](create-onboarding) olmanız gerekir. 3. Onboarding'i bir [placement](placements)'a eklemiş olmanız gerekir. ## Onboarding'i getir \{#fetch-onboarding\} No-code oluşturucumuzla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirip görüntülemesi gereken bir yapılandırma içeren konteyner olarak saklanır. Bu konteyner tüm deneyimi yönetir; hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (sınav cevapları veya form girişleri gibi) nasıl işleneceğini belirler. Konteyner aynı zamanda analitik olaylarını otomatik olarak takip eder, bu nedenle ayrıca görüntüleme takibi yapmanıza gerek yoktur. En iyi performans için, kullanıcılara göstermeden önce görsellerin indirilmesine yetecek süreyi tanımak amacıyla onboarding yapılandırmasını erken getirin. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```swift showLineNumbers do { let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID") // the requested onboarding } catch { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding lokalizasyonunun tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenmektedir. İlk alt etiket dil için, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Dil kodları ve bunların nasıl kullanılması önerildiği hakkında daha fazla bilgi için [Lokalizasyonlar ve dil kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla başa çıktığını düşünüyorsanız, önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadiren de olsa bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikler içeren bir [`AdaptyOnboarding`](https://swift.adapty.io/documentation/adapty/adaptyonboarding) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding getirmeyi hızlandır \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz varken kullanıcılarınızın internet bağlantısı zayıfsa, onboarding getirme işlemi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için onboarding'i getiren `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Onboarding'i Getir](#fetch-onboarding) bölümünde açıklandığı gibi `getOnboarding` metoduyla onboarding getirmek olduğunu anlamak çok önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı düşünün; çünkü birincisinin önemli kısıtlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlar yaratabilir; ya geriye dönük uyumlu tasarımlar yapmanızı ya da eski sürümlerin yanlış görünebileceğini kabul etmenizi gerektirir. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel özniteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı getirme bu dezavantajlardan daha önemliyse, aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde, [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```swift showLineNumbers Adapty.getOnboardingForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(onboarding): // the requested onboarding case let .failure(error): // handle the error } } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding lokalizasyonunun tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenmektedir. İlk alt etiket dil için, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Dil kodları ve bunların nasıl kullanılması önerildiği hakkında daha fazla bilgi için [Lokalizasyonlar ve dil kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla başa çıktığını düşünüyorsanız, önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | --- # File: ios-present-onboardings --- --- title: "iOS SDK'da onboardingları sunma" description: "iOS'ta dönüşümleri ve geliri artırmak için onboardingları nasıl sunacağınızı keşfedin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. Onboarding'ler WebView içinde çalışırken, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları edinme](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) sayfalarına göz atın. ::: Builder ile bir onboarding özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir onboarding, hem onboarding içinde ne gösterileceğini hem de nasıl gösterileceğini içerir. Başlamadan önce şunları sağlayın: 1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0 veya üzerini yüklemiş olun. 2. Bir [onboarding oluşturmuş](create-onboarding) olun. 3. Onboardingı bir [placement](placements)'a eklemiş olun. ## Swift'te onboardingları sunma \{#present-onboardings-in-swift\} Görsel onboardingı cihaz ekranında göstermek için şu adımları izleyin: 1. `.getOnboardingConfiguration` metodunu kullanarak onboarding görünüm yapılandırmasını alın. 2. Görüntülemek istediğiniz görsel onboardingı `.onboardingController` metodunu kullanarak başlatın: İstek parametreleri: | Parametre | Zorunluluk | Açıklama | |:--------------------------------|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding configuration** | zorunlu | Tüm onboarding özelliklerini içeren bir `AdaptyUI.OnboardingConfiguration` nesnesi. Bunu elde etmek için `AdaptyUI.getOnboardingConfiguration` metodunu kullanın. | | **delegate** | zorunlu | Onboarding olaylarını dinlemek için bir `AdaptyOnboardingControllerDelegate`. | Döndürür: | Nesne | Açıklama | |:-------------------------------|:--------------------------------------------------------| | **AdaptyOnboardingController** | İstenen onboarding ekranını temsil eden bir nesne | 3. Nesne başarıyla oluşturulduktan sonra cihaz ekranında görüntüleyebilirsiniz: ```swift showLineNumbers title="Swift" import Adapty import AdaptyUI // 0. Get an onboarding if you haven't done it yet let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID") // 1. Obtain the onboarding view configuration: let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding) // 2. Create Onboarding View Controller let onboardingController = try AdaptyUI.onboardingController( with: configuration, delegate: <AdaptyOnboardingControllerDelegate> ) // 3. Present it to the user present(onboardingController, animated: true) ``` ## SwiftUI'da onboardingları sunma \{#present-onboardings-in-swiftui\} SwiftUI'da görsel onboardingı cihaz ekranında göstermek için: ```swift showLineNumbers title="SwiftUI" // 1. Obtain the onboarding view configuration: let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding) // 2. Display the Onboarding View within your view hierarchy AdaptyOnboardingView( configuration: configuration, placeholder: { Text("Your Placeholder View") }, onCloseAction: { action in // hide the onboarding view }, onError: { error in // handle the error } ) ``` ## Splash ekranı ile onboarding arasına yumuşak geçiş ekleme \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\} Varsayılan olarak, splash ekranı ile onboarding arasında onboarding tam olarak yüklenene kadar yükleme ekranı görünür. Ancak geçişi daha pürüzsüz hale getirmek istiyorsanız, bunu özelleştirebilir; splash ekranını uzatabilir ya da başka bir şey gösterebilirsiniz. Bunun için bir placeholder tanımlayın (onboarding yüklenirken tam olarak ne gösterileceğini belirleyin). Bir placeholder tanımlarsanız, onboarding arka planda yüklenir ve hazır olduğunda otomatik olarak gösterilir. <Tabs> <TabItem value="swift" label="UIKit"> ```swift showLineNumbers extension YourOnboardingManagerClass: AdaptyOnboardingControllerDelegate { func onboardingsControllerLoadingPlaceholder( _ controller: AdaptyOnboardingController ) -> UIView? { // instantiate and return the UIView which will be presented while onboarding is being loaded } } ``` </TabItem> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers AdaptyOnboardingView( configuration: configuration, placeholder: { // define your placeholder view, which will be presented while onboarding is being loaded }, // the rest of the implementation ) ``` </TabItem> </Tabs> ## Onboarding'lerdeki bağlantıların nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboarding'lerdeki bağlantıların nasıl açılacağını özelleştirme özelliği Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboarding'lerdeki bağlantılar uygulama içi bir tarayıcıda açılır. Bu, kullanıcıların uygulama değiştirmeden web sayfalarını görüntüleyebilmesini sağlayarak kesintisiz bir kullanıcı deneyimi sunar. Bağlantıların bunun yerine harici bir tarayıcıda açılmasını tercih ederseniz, `externalUrlsPresentation` parametresini `.externalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```swift showLineNumbers let configuration = try AdaptyUI.getOnboardingConfiguration( forOnboarding: onboarding, externalUrlsPresentation: .externalBrowser // default – .inAppBrowser ) ``` --- # File: ios-handling-onboarding-events --- --- title: "iOS SDK'da onboarding olaylarını yönetme" description: "Adapty kullanarak iOS'ta onboarding ile ilgili olayları yönetin." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları alma](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) konularına bakın. ::: Başlamadan önce şunların sağlandığından emin olun: 1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0 veya daha yeni bir sürümü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyOnboardingControllerDelegate` metodlarını uygulayın. ## Özel eylemler \{#custom-actions\} Builder'da bir düğmeye **özel** bir eylem ekleyip bu eyleme bir ID atayabilirsiniz. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu ID'yi kodunuzda kullanarak özel bir eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir düğmeye dokunduğunda, delegate metodu `onboardingController`, `.custom(id:)` durumuyla tetiklenir ve `actionId` parametresi builder'daki **Action ID**'dir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) { if action.actionId == "allowNotifications" { // Request notification permissions } } func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) { // Handle errors } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## Onboarding'i kapatma \{#closing-onboarding\} Bir kullanıcı **Close** eylemi atanmış bir düğmeye dokunduğunda onboarding kapatılmış sayılır. <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Kullanıcı onboarding'i kapattığında ne olacağını siz yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini görüntülemeyi durdurmanız gerekir. ::: Örneğin: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) { controller.dismiss(animated: true) } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## Paywall açma \{#opening-a-paywall\} :::tip Onboarding içinde bir paywall açmak istiyorsanız bu eventi işleyin. Paywall kapandıktan sonra açmak istiyorsanız daha kolay bir yol var: [`AdaptyOnboardingsCloseAction`](#closing-onboarding) eventini işleyin ve event verisine dayanmadan paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, action ID'yi bir paywall placement ID'siyle eşit yapmaktır. Bu sayede `AdaptyOnboardingsOpenPaywallAction` sonrasında placement ID'yi kullanarak paywall'ı hemen alıp açabilirsiniz. Ekranda aynı anda yalnızca bir görünümün (paywall veya onboarding) görüntülenebileceğini unutmayın. Bir onboarding'in üzerine paywall sunarsanız arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışmak bunun yerine paywall'u kapatır ve onboarding görünür kalır. Bunu önlemek için paywall'u sunmadan önce her zaman onboarding görünümünü kapatın. ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onPaywallAction action: AdaptyOnboardingsOpenPaywallAction) { // Dismiss onboarding before presenting the flow controller.dismiss(animated: true) { Task { do { // Get the flow using the placement ID from the action let flow = try await Adapty.getFlow(placementId: action.actionId) // Get the flow configuration let flowConfiguration = try await AdaptyUI.getFlowConfiguration( forFlow: flow ) // Create and present the flow controller let flowController = try AdaptyUI.flowController( with: flowConfiguration, delegate: self ) // Present the flow from the root view controller if let rootVC = UIApplication.shared.windows.first?.rootViewController { rootVC.present(flowController, animated: true) } } catch { // Handle any errors that occur during flow loading print("Failed to present flow: \(error)") } } } } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## Onboarding yüklemesini tamamlama \{#finishing-loading-onboarding\} Bir onboarding yüklemeyi tamamladığında bu metod çağrılır: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, didFinishLoading action: OnboardingsDidFinishLoadingAction) { // Handle loading completion } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## Navigasyonu izleme \{#tracking-navigation\} `onAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır. `event` nesnesi aşağıdaki türlerden biri olabilir: |Tür | Açıklama | |------------|-------------| | `onboardingStarted` | Onboarding yüklendiğinde | | `screenPresented` | Herhangi bir ekran gösterildiğinde | | `screenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcıdan gelen yanıt) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `secondScreenPresented` | İkinci ekran gösterildiğinde | | `userEmailCollected` | Kullanıcının e-postası giriş alanı üzerinden toplandığında tetiklenir | | `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa [son ekrana `final` ID'sini atayın](design-onboarding). | | `unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek metadata) içerir | Her olay şu alanları içeren `meta` bilgisi barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Akıştaki mevcut ekranın konumu | | `screensTotal` | Akıştaki toplam ekran sayısı | Analitik olayları izleme amacıyla nasıl kullanabileceğinize dair bir örnek: ```swift func onboardingController(_ controller: AdaptyOnboardingController, onAnalyticsEvent event: AdaptyOnboardingsAnalyticsEvent) { switch event { case .onboardingStarted(let meta): // Track onboarding start trackEvent("onboarding_started", meta: meta) case .screenPresented(let meta): // Track screen presentation trackEvent("screen_presented", meta: meta) case .screenCompleted(let meta, let elementId, let reply): // Track screen completion with user response trackEvent("screen_completed", meta: meta, elementId: elementId, reply: reply) case .onboardingCompleted(let meta): // Track successful onboarding completion trackEvent("onboarding_completed", meta: meta) case .unknown(let meta, let name): // Handle unknown events trackEvent(name, meta: meta) // Handle other cases as needed } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: ios-onboarding-input --- --- title: "iOS SDK'da onboarding verilerini işleme" description: "Adapty SDK ile iOS uygulamanızdaki onboarding verilerini kaydedin ve kullanın." --- :::tip **SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. Onboarding'ler WebView içinde çalışırken flow'lar cihazda native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall'ları alma](get-pb-paywalls) ve [Flow ve paywall'ları gösterme](ios-present-paywalls) sayfalarına bakın. ::: Kullanıcılarınız bir sınav sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Store user preferences or responses switch action.params { case .select(let params): // Handle single selection case .multiSelect(let params): // Handle multiple selections case .input(let params): // Handle text input case .datePicker(let params): // Handle date selection } } ``` `action` nesnesi şunları içerir: | Parametre | Açıklama | |----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `elementId` | Giriş öğesi için benzersiz bir tanımlayıcı. Soruları yanıtlarla ilişkilendirmek için kullanabilirsiniz. | | `params` | Tür ve değer özelliklerini içeren kullanıcının giriş verisi nesnesi. | | `params.type` | Giriş öğesinin türü. Şunlardan biri olabilir:<br/>• `"select"` - Seçeneklerden tek seçim<br/>• `"multiSelect"` - Seçeneklerden çoklu seçim<br/>• `"input"` - Metin giriş alanı<br/>• `"datePicker"` - Tarih seçimi | | `params.value` | Kullanıcının seçtiği veya girdiği değer(ler). Yapısı türe göre değişir:<br/>• `select`: `id`, `value`, `label` içeren nesne<br/>• `multiSelect`: `id`, `value`, `label` içeren nesnelerden oluşan dizi<br/>• `input`: `type`, `value` içeren nesne<br/>• `datePicker`: `day`, `month`, `year` içeren nesne | <Details> <summary>Kaydedilen veri örnekleri (uygulamanızda farklılık gösterebilir)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Giriş verilerini kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](setting-user-attributes) giriş verileriyle güncellemeniz gerekir. Örneğin, kullanıcılardan `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmelerini de istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Store user preferences or responses switch action.params { case .input(let params): // Handle text input let builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field switch action.elementId { case "name": builder.with(firstName: params.value.value) case "email": builder.with(email: params.value.value) default: break } // Delegate methods are synchronous; kick off the async update in a Task. Task { do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } } default: break } } ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboardinglardaki testleri kullanarak, kullanıcıların onboarding'i tamamlamasının ardından gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara spor deneyimlerini sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding oluşturucuya [bir test ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın. 2. Test yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler belirleyin](setting-user-attributes). ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Handle quiz responses and set custom attributes switch action.params { case .select(let params): // Handle quiz selection let builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes switch action.elementId { case "experience": // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) try? builder.with(customAttribute: params.value.value, forKey: "experience") default: break } // Delegate methods are synchronous; kick off the async update in a Task. Task { do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } } default: break } } ``` 3. Her özel nitelik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda placement için [bir paywall görüntüleyin](ios-paywalls). Onboarding'inizde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](ios-handling-onboarding-events#opening-a-paywall) olarak uygulayın. --- # File: ios-sdk-call-order --- --- title: "iOS SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak premium erişim kaybını, eksik attribution'ı ve aralıklı #2002 hatalarını önleyin." --- `Adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağırmamalısınız. Bu metod sonuçlanmadan SDK'nın herhangi bir durumu yoktur. `activate()` ile eş zamanlı ya da öncesinde yapılan her çağrı [`#2002 notActivated`](ios-sdk-error-handling#network-errors) hatasıyla başarısız olur. Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, bu noktada `Adapty.identify()` çağrısı yapın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metodları çağırmayın. Bu çağrıyla yarışan işlemler ya [`#3006 profileWasChanged`](ios-sdk-error-handling#general-errors) hatasıyla başarısız olur ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP kimlik bilgileri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `Adapty.activate` çağrısından önce bunları başlatın ve UID callback'lerini bekleyin. Aksi takdirde MMP ID'si kısa ömürlü anonim bir profile düşer ve tanımlı profile her zaman aktarılamaz. AppsFlyer'a özgü ayrıntılar için bkz. [AppsFlyer](appsflyer). ## Doğru sıra \{#the-correct-order\} Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK metotlarını çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK (AppsFlyer, Adjust, Branch, PostHog) entegre ediyorsanız gereklidir. - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama başlatıldığında müşteri kullanıcı kimliğine sahipseniz, doğrudan `activate()` fonksiyonuna aktarın (adım 2a). Bu yöntem hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gereksizdir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlatılırken, ilk önce | MMP'nin UID geri çağırmasını bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `Adapty.activate(with: config)` — config üzerinde `customerUserId` ayarlanmış | Uygulama başlatılırken, 1. adımdan sonra, customer user ID'niz varsa | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `Adapty.activate(with: config)` — `customerUserId` olmadan | Uygulama başlatılırken, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplanmıyorsa) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty.setIntegrationIdentifier(...)` | 2. adımdan sonra, herhangi bir kullanıcı eylemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için zorunludur. | | 4 | `try await Adapty.identify("YOUR_USER_ID")` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulama ile 2b yolunda | Her zaman `await` kullanın. `identify` sırasında eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar. | | 5 | `getPaywall`, `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi takdirde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::important Bu adımları atlamak; geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitleye karşı döndürülen paywalls'a yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar bir web ödeme sayfasından (Stripe, Paddle, FunnelFox) satın alıp ardından uygulamayı yüklerse, cihazın ilk `activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Uygulama başlatılmadan önce kullanıcı kimliğini (auth akışından veya install referrer'dan) çözümleyebiliyorsanız, doğrudan `activate()` içine geçirin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` ve ardından `restorePurchases` çağrısı yapılana kadar cihazda görünmez. Her web ödeme sayfasıyla gönderilecek metadata için şuralara bakın: - [Stripe](stripe) - [Paddle](paddle) --- # File: ios-optimize-paywall-fetching --- --- title: "iOS SDK'da paywall getirme işlemini optimize etme" description: "Adapty paywall'larını güvenilir şekilde getirin: iOS için zamanlama, önbellekleme ve yedek desenleri." --- iOS'ta güvenilir bir paywall getirme işlemi üç şeyi başarır: hızlı render eder, kitleyeye hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz yedek sunar. Aşağıdaki kurallar bunu sağlamak için zamanlama, önbellekleme ve yedek desenlerini kapsar. :::tip Bu kurallar, `Adapty.activate()` ve `Adapty.identify()` işlemlerinin tamamlandığını varsayar. Bkz. [iOS SDK'da çağrı sırası](ios-sdk-call-order). ::: ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Bunu yap | Bunu yapma | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı çekin. | Başlangıçta tüm placement'ları eş zamanlı olarak önceden çekin. | Toplu önceden çekme ana thread'i bloke eder ve burst sırasında siyah ekrana yol açar. | | `getPaywall` işlevini attribution'ın çözülmesine fırsat tanıdıktan sonra çekin — örneğin `activate` işlevinden 1–2 saniye sonra ya da `onProfileUpdate` tetiklendikten sonra. | `getPaywall` işlevini `App.init()` sırasında çağırın. | Attribution henüz gelmemiştir. Paywall, varsayılan kitleye göre çözümlenir ve segmentleri ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall` işleminin bitmesini süresiz bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf olan kullanıcılar ağ çözülene kadar boş bir ekran görür — ya da uygulamayı kapatır. | `fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products) sayfasına, doğru placement'ı seçmek için ise [Placement'lar](placements) sayfasına bakın. ## Bağlantı sorunları için ayarlar \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantının yaşandığı pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunlarından etkilenen bölgeler): - İlk fetch dışında her fetch işleminde `fetchPolicy: .returnCacheDataElseLoad` kullanın. - Adapty Kontrol Paneli'ndeki her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalla geçin. - Paywall gösterimini `getProfile()` sonucuna bağlamayın. `getPaywall` işlemini bağımsız olarak çağırın; böylece yavaş bir profil yüklemesi arayüzü bloke etmez. --- # File: ios-show-aa-targeted-paywall --- --- title: "iOS SDK'da ilk başlatmada AA hedefli paywall gösterme" description: "AdaptyProfile.appliedAttributionSources kullanarak iOS'ta paywall istemeden önce Apple Ads attribution'ını bekleyin." --- Apple Ads (AA) attribution, `Adapty.activate()` çağrısından sonra asenkron olarak gelir. `getPaywall` fonksiyonunu erken çağırırsanız, attribution henüz gelmemiş olabilir ve Adapty, placement'ı varsayılan kitle üzerinden çözümleyerek AA segmentine göre ayarlanmış paywallları atlayabilir. `AdaptyProfile.appliedAttributionSources`, uygulamanın AA attribution'ının profile uygulanıp uygulanmadığını tespit etmesini sağlar; böylece paywall isteği, AA segmentasyonunun doğru şekilde çözümleneceği ana kadar bekletilebilir. ## Başlamadan önce \{#before-you-start\} İhtiyacınız olanlar: - Adapty iOS SDK **3.17.1** veya üzeri. - Uygulamanız için Adapty'de Apple Ads yapılandırılmış olması. Bkz. [Apple Ads](apple-search-ads). ## Nasıl çalışır \{#how-it-works\} `Adapty.activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution bilgisini talep eder ve sonucu Adapty'nin backend'ine iletir. AA, profil için aktif attribution kaynağı haline geldiğinde SDK, `appliedAttributionSources` dizisinde `.appleAds` içeren güncellenmiş bir `AdaptyProfile` döndürür. Boş bir dizi şu anlara gelebilir: - Bu profil için Apple Ads attribution henüz işlenmemiş olabilir. - Hiç attribution gelmemiş olabilir. Boş bir dizi ile bile `getPaywall` çağrısı güvenlidir — Adapty, isteği mevcut profil durumuna uyan kitleye göre (genellikle varsayılan kitle) çözümler. :::important Bekleme yalnızca **ilk başlatma** için geçerlidir. Apple Ads attribution kaydedildikten sonra profilde kalıcı olarak saklanır. Sonraki her başlatmada önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `.appleAds` değerini taşır, `didLoadLatestProfile` bu değerle anında tetiklenir ve `getPaywall` herhangi bir gecikme olmadan Apple Ads segmentine uygun paywall'ı döndürür. ::: ## Uygulama \{#implementation\} İlk açılışta profilde `.appleAds` değerini izleyin ve sert bir zaman aşımı uygulayın — Apple Ads attribution hiç gelmese bile, o kullanıcıların yine de bir paywall görmesi gerekir. 1. **SDK'yı etkinleştirin.** Bkz. [iOS SDK'yı yükle ve yapılandır](sdk-installation-ios). 2. **Profil güncellemelerini dinleyin:** `AdaptyDelegate`'e uyum sağlayarak `didLoadLatestProfile`'ı uygulayın. Delegate'i henüz ayarlamadıysanız bkz. [Abonelik güncellemelerini dinle](ios-check-subscription-status#listen-to-subscription-updates). 3. **`appliedAttributionSources` içinde `.appleAds` çıkıp çıkmadığını takip edin.** Göründüğünde paywall'ı isteyin — Adapty, AA segmentine göre belirlenmiş varyantı döndürecektir: ```swift extension <YourAdaptyDelegateImpl>: AdaptyDelegate { nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { if profile.appliedAttributionSources.contains(where: { $0 == .appleAds }) { // load paywall via Adapty.getPaywall(placementId:) } } } ``` 4. **Abonelikle paralel olarak 3–5 saniyelik bir zamanlayıcı başlatın.** Zamanlayıcı `.appleAds` görünmeden tetiklenirse, yine de paywallı isteyin: Hangi yol önce tetiklenirse o ywall'ı yüklemeli; diğer yol atlanmalıdır. Paywall'ın iki kez getirilmemesi için tek bir durum bayrağı (örneğin `hasLoadedPaywall`) kullanarak yinelenenleri ortadan kaldırın. Ağ isteği başarısız olduğunda kullanıcının askıda kalmaması için placement'a bir [yedek paywall](fallback-paywalls) yapılandırın. ## Eksiksiz örnek \{#complete-example\} Aşağıdaki implementasyon, attribution ile bir zaman aşımını yarıştırır, varsayılan kitle paywallını paralel olarak önceden çeker ve uygun olan paywallı döndürür. Çağıran taraf yalnızca tek bir async fonksiyonu bekler; çağrı noktasında yönetilmesi gereken delegate veya durum bayrağı yoktur. `ProfileObserver`, `AdaptyDelegate`'ten gelen profil güncellemelerini yayınlayan yeniden kullanılabilir bir singleton'dır. `PaywallLoader.getPaywallOrDefault` ise yarışı yapılandırılmış eşzamanlılık `TaskGroup` kullanarak yürütür: - Attribution `timeout` süresi içinde gelirse, `getPaywall(placementId:)` aracılığıyla segmentlere ayrılmış paywall döndürülür. - `timeout` süresi önce dolarsa, `getPaywallForDefaultAudience(placementId:)` aracılığıyla önceden yüklenmiş varsayılan kitle paywall'u döndürülür. ```swift title="PaywallLoader.swift" /// Attribution uygulanmasına bağlı bir paywallın nasıl getirileceğini gösterir; /// attribution zamanında gelmezse varsayılan kitle paywallına geri düşer. /// /// Durumsuz ve bağımsızdır: her çağrı kendi varsayılan kitle ön getirme işlemini /// başlatır ve bunu attribution + segmentli getirme ile yarıştırır. enum PaywallLoader { static func getPaywallOrDefault( placementId: String, timeout: TimeInterval ) async throws -> AdaptyPaywall { struct TimedOut: Error {} // Varsayılan kitle isteğini hemen başlat; böylece yüklemek için tam // `timeout` süresi olur. Başarı durumunda iptal edilir, zaman aşımında // sonucu beklenir — hiçbir zaman yinelenen ağ çağrısı yapılmaz. let defaultPaywallTask = Task { try await Adapty.getPaywallForDefaultAudience(placementId: placementId) } do { // İki alt görevi yarıştır: hangisi önce biterse o kazanır. let result = try await withThrowingTaskGroup(of: AdaptyPaywall.self) { group in // 1. Attribution'ı bekle, ardından Adapty'den segmentli paywallı iste. group.addTask { await waitForAttribution() return try await Adapty.getPaywall(placementId: placementId) } // 2. Zaman bombası: `timeout` saniye sonra `TimedOut` fırlatır. group.addTask { try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000)) throw TimedOut() } guard let value = try await group.next() else { throw CancellationError() } group.cancelAll() // Kaybedeni durdur (uyuyan görev veya attribution bekleyen). return value } // Segmentli paywall kazandı — varsayılan kitle ön getirme artık gerekli değil. defaultPaywallTask.cancel() return result } catch is TimedOut { // Attribution zamanında uygulanamadı — önceden yüklenen varsayılanı döndür // (zaten tamamlandıysa anında, değilse devam eden isteği bekle). return try await defaultPaywallTask.value } } /// İstenen attribution kaynağına sahip bir profil gözlemlenene kadar askıya alır. /// `@Published.values`, abonelikte mevcut profili hemen yayımlar; bu nedenle /// attribution zaten uygulanmışsa ilk iterasyonda geri döner. @MainActor private static func waitForAttribution() async { for await profile in ProfileObserver.shared.$profile.values { if profile?.appliedAttributionSources.contains(.appleAds) == true { return } } } } @MainActor final class ProfileObserver: AdaptyDelegate { static let shared = ProfileObserver() @Published private(set) var profile: AdaptyProfile? nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { Task { @MainActor [weak self] in self?.profile = profile } } } ``` `Adapty.activate()` tamamlandıktan sonra `ProfileObserver`'ı `AdaptyDelegate`'e bir kez bağlayın: ```swift Adapty.delegate = ProfileObserver.shared ``` Splash ekranından çağırın: ```swift do { let paywall = try await PaywallLoader.getPaywallOrDefault( placementId: "YOUR_PLACEMENT_ID", timeout: 5 ) // paywallı göster } catch { // hatayı yönet veya yedek paywall göster } ``` Uygulamanız başka amaçlar için zaten bir `AdaptyDelegate` kullanıyorsa (örneğin, [abonelik güncellemelerini dinlemek](ios-check-subscription-status#listen-to-subscription-updates) için), `Adapty.delegate = ProfileObserver.shared` yapmak yerine mevcut delegate'inizden `didLoadLatestProfile`'ı `ProfileObserver.shared`'a iletin. --- # File: ios-test --- --- title: "iOS SDK'da Test & Yayınlama" description: "Adapty ile iOS uygulamanızdaki abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Adapty SDK'yı iOS uygulamanıza zaten entegre ettiyseniz, her şeyin doğru kurulduğunu ve satın almaların beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de gerçek satın alma işlemini test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Sandbox testi ve TestFlight doğrulaması dahil olmak üzere uygulama içi satın almalarınızı kapsamlı şekilde test etmek için [test kılavuzumuza](test-purchases-in-sandbox) göz atın. ## Yayına hazırlanın \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce, aşağıdakileri doğrulamak için [Yayın kontrol listesini](release-checklist) takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırıldı - Satın almalar tamamlanıyor ve Adapty'ye raporlanıyor - Erişim doğru şekilde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılandı --- # File: InvalidProductIdentifiers --- --- title: "Code-1000 noProductIDsFound hatası için çözüm" description: "Adapty'de abonelikleri yönetirken geçersiz ürün tanımlayıcısı hatalarını çözün." --- 1000 kodlu `noProductIDsFound` hatası, paywall'da istediğiniz ürünlerin App Store'da listelenmiş olmasına rağmen satın alma için kullanılamadığını gösterir. Bu hata zaman zaman `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız tek başına görünüyorsa görmezden gelebilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız sorunu çözmek için şu adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne geçin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümünde listelenmiş şekilde göreceksiniz. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. Değilse [App Store'daki Ürün](app-store-products) sayfasındaki talimatları izleyin. <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Tablodaki ürün kimliğini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesindekiyle karşılaştırın. Kimlikler eşleşmiyorsa ürün kimliğini tablodan kopyalayın ve Adapty Kontrol Paneli'nde bu kimlikle [ürün oluşturun](create-product). <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** bölümüne inin ve gerekli tüm ülke ve bölgelerin listelendiğini doğrulayın. <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'teki **Monetization** → **Subscriptions** bölümüne tekrar gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** bölümüne inin ve **Current Pricing for New Subscribers** kısmını genişletin. <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Gerekli tüm fiyatların listelendiğinden emin olun. <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. Uygulama ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. **[App Store Connect](https://appstoreconnect.apple.com/)** ana sayfasında **Business** seçeneğine tıklayın. <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şirket adınızı seçin. 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** başlıklarının hepsinin **Active** olarak göründüğünü doğrulayın. Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayınlayabilirsiniz. ## Adım 6. Ürün takıldıysa yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5 arası adımların tamamı başarıyla geçebilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — yine de SDK `1000 noProductIDsFound` hatası döndürmeye devam edebilir. Bu durumda ürün Apple'ın kayıt sisteminde takılı kalmış olabilir. Apple'ın ürün kayıt sistemi zaman zaman öyle bir duruma girer ki ürün App Store Connect arayüzünde görünür ama StoreKit arama yoluna açık değildir. Ürünü App Store Connect'ten silin ve aynı ürün kimliğiyle yeniden oluşturun. Yayılmanın tamamlanması için yeniden oluşturmanın ardından 24 saate kadar bekleyin. --- # File: cantMakePayments --- --- title: "Code-1003 cantMakePayment hatasının çözümü" description: "Adapty'de abonelikleri yönetirken ödeme yapılamıyor hatasını çözün." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: migration-to-ios-sdk-v4 --- --- title: "Adapty iOS SDK'yı v4.0'a Geçirin" description: "Adapty iOS SDK v4.0'a geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty iOS SDK 4.0, flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı referans \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty.getPaywall(placementId:locale:)` | `Adapty.getFlow(placementId:)` | | `AdaptyUI.getPaywallConfiguration(forPaywall:)` | `AdaptyUI.getFlowConfiguration(forFlow:locale:)` | | `Adapty.getPaywallProducts(paywall:)` | `Adapty.getPaywallProducts(flow:)` | | `Adapty.logShowPaywall(_:)` | `Adapty.logShowFlow(_:)` | | `AdaptyPaywallController` | `AdaptyFlowController` | | `AdaptyPaywallControllerDelegate` | `AdaptyFlowControllerDelegate` | | `AdaptyUI.paywallController(with:delegate:)` | `AdaptyUI.flowController(with:delegate:)` | | `.paywall()` (SwiftUI modifier) | `.flow()` | | `AdaptyPaywallView` | `AdaptyFlowView` | | `didFailRenderingWith:` / `didFailRendering:` | `didReceiveError:` | | `didFinishPurchase` (isteğe bağlı, başarıda otomatik kapanır) | `didFinishPurchase` (zorunlu, otomatik kapanma yok) | | `Adapty_KidsMode` / `AdaptyUI_KidsMode` paket ürünleri | `KidsMode` paket trait'i | | `Adapty.updateAttribution(_:source:)` (`source: String`) | `Adapty.updateAttribution(_:source:)` (`source: AdaptyAttributionSource`) | | `Adapty.setIntegrationIdentifier(key:value:)` | `Adapty.setIntegrationIdentifier(_:)` (`AdaptyIntegrationIdentifier`) | ## Minimum iOS sürümü \{#minimum-ios-version\} Adapty iOS SDK 4.0, minimum deployment target'ı iOS 13.0'dan **iOS 15.0**'a yükseltiyor. Yükseltmeden önce projenizin iOS Deployment Target'ını 15.0 veya üzerine ayarlayın. ## Kurulum: CocoaPods artık desteklenmiyor \{#installation-cocoapods-no-longer-supported\} Adapty iOS SDK 4.0, CocoaPods desteğini kaldırdı. SDK'yı [Swift Package Manager](sdk-installation-ios#install-adapty-sdk) ile yükleyin. Projeniz hâlâ CocoaPods kullanıyorsa `Podfile` dosyanızdan `Adapty` ve `AdaptyUI` pod'larını kaldırın, `pod install` çalıştırarak temizleyin, ardından Xcode'da **File → Add Package Dependency** seçeneğiyle `https://github.com/adaptyteam/AdaptySDK-iOS.git` adresini kullanarak paketi ekleyin. ## Kids Mode: ayrı ürünler bir paket özelliğiyle değiştirildi \{#kids-mode-separate-products-replaced-by-a-package-trait\} v3'te, [Kids Mode](kids-mode)'u etkinleştirmek için ayrı **Adapty_KidsMode** ve **AdaptyUI_KidsMode** paket ürünlerini seçiyor ve importlarınızı yeniden adlandırıyordunuz. v4.0'da bu ürünler kaldırıldı. Kids Mode artık normal Adapty paketinde `KidsMode` adlı bir Swift paket özelliği — etkinleştirildiğinde IDFA ve AdSupport'u tüm SDK genelinde derlemenin dışında bırakır. Geçiş yapmak için: 1. **Choose Package Products** penceresinde, **Adapty_KidsMode** ve **AdaptyUI_KidsMode** yerine normal **Adapty** ve **AdaptyUI** ürünlerini seçin. 2. `KidsMode` trait'ini etkinleştirin. Xcode 26.4 veya sonraki bir sürümde, projenizin **Package Dependencies** görünümünde AdaptySDK-iOS bağımlılığı için etkinleştirin. Adapty'yi `Package.swift` içine bağımlılık olarak ekliyorsanız (`swift-tools-version` 6.1 veya sonrası gereklidir), orada etkinleştirin: ```swift showLineNumbers title="Package.swift" .package( url: "https://github.com/adaptyteam/AdaptySDK-iOS.git", from: "4.0.0", traits: ["KidsMode"] ) ``` 3. Import'larınızı tekrar normal modüllere geri alın: ```diff showLineNumbers - import Adapty_KidsMode - import AdaptyUI_KidsMode + import Adapty + import AdaptyUI ``` :::note 26.4'ten eski Xcode sürümleri, bir Xcode projesinde trait'leri arayüzden etkinleştiremez. Bu durumda, `KidsMode` trait'i etkin şekilde Adapty'ye bağımlı küçük bir yerel Swift paketi oluşturun ve uygulama hedefinizi bu pakete bağımlı yapın. ::: ## Kaldırılan API'ler \{#removed-apis\} - **`Adapty.getPaywallProductsWithoutDeterminingOffer(paywall:)`** — kaldırıldı. Artık tüm ürünler teklif bilgisini içerdiğinden, ayrı bir uygunluk kontrolü adımına gerek kalmadı. - **`AdaptyPaywallProductWithoutDeterminingOffer`** — kaldırıldı. Daha önce bu türü (örneğin `didSelectProduct` gibi) callback'lere geçiren yapılar artık `AdaptyPaywallProduct` kullanıyor. ## App Store tanıtılan uygulama içi satın almalar geçici olarak kaldırıldı \{#app-store-promoted-in-app-purchases-temporarily-removed\} StoreKit 2 geçişinin bir parçası olarak, Adapty iOS SDK 4.0, App Store tanıtılan uygulama içi satın almalar için desteği kaldırdı. `shouldAddStorePayment(for:)` delegate metodu ve aldığı `AdaptyDeferredProduct` türü 4.0'da kullanılamamaktadır. :::warning Bu kaldırma işlemi geçicidir — tanıtılan uygulama içi satın alma desteği daha sonraki bir 4.x sürümünde geri dönecektir. Uygulamanız tanıtılan uygulama içi satın almalara dayanıyorsa, destek geri dönene kadar iOS SDK 3.x sürümünde kalmaya devam edin. ::: ## Paywall'ları Getirme \{#fetching-paywalls\} ### getPaywall + getPaywallConfiguration → getFlow + getFlowConfiguration Döndürülen türler `AdaptyPaywall` / `AdaptyUI.PaywallConfiguration` yerine `AdaptyFlow` / `AdaptyUI.FlowConfiguration` olarak değişiyor. `locale` parametresi fetch çağrısından çıkarılıp `getFlowConfiguration` üzerine taşınıyor: ```diff showLineNumbers - let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") - let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(forPaywall: paywall) + let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") + let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow, locale: "en") ``` ### getPaywallProducts(paywall:) → getPaywallProducts(flow:) `getPaywallProducts` artık `Adapty.getFlow` tarafından döndürülen bir `AdaptyFlow` alıyor: ```diff showLineNumbers - let products = try await Adapty.getPaywallProducts(paywall: paywall) + let products = try await Adapty.getPaywallProducts(flow: flow) ``` ## Paywall görüntülemelerini takip etme \{#tracking-paywall-views\} ### logShowPaywall(_:) → logShowFlow(_:) `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık `AdaptyPaywall` yerine `AdaptyFlow` alıyor. Olay hâlâ aynı varyasyona karşı kaydedildiği için mevcut dönüşüm hunisi ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder. ```diff showLineNumbers - try await Adapty.logShowPaywall(paywall) + try await Adapty.logShowFlow(flow) ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow veya paywall'ları görüntülerken bu metodu çağırmanız gerekmez — Adapty bu görüntülemeleri otomatik olarak takip eder. ## didFinishPurchase artık zorunlu \{#didfinishpurchase-is-now-required\} v3'te `didFinishPurchase` isteğe bağlıydı: uygulamamanız durumunda, başarılı bir satın alma işleminin ardından paywall kendiliğinden kapanıyordu. v4.0'da bu varsayılan otomatik kapanma davranışı kaldırıldı; böylece başarılı bir satın alma işleminin ardından flow devam edebilir — örneğin flow'unuzun geri kalan ekranlarını göstermek için. Satın alma işleminin ardından ne olacağına artık siz karar veriyorsunuz: ekranı kapatın ya da flow'un devam etmesine izin vermek için hiçbir şey yapmayın. - **UIKit**: `AdaptyFlowControllerDelegate` uyumluları artık `didFinishPurchase` metodunu uygulamak zorundadır — bu metodun artık varsayılan bir implementasyonu yoktur. - **SwiftUI**: `.flow(...)` ve `AdaptyFlowView(...)` içindeki `didFinishPurchase` closure'ı artık zorunludur (non-optional); bu durum `didFailPurchase` ve `didFinishRestore` ile tutarlı hale getirilmiştir. v3 davranışını korumak için ekranı kendiniz kapatın: ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didFinishPurchase product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { if !purchaseResult.isPurchaseCancelled { controller.dismiss(animated: true) } } ``` ## UIKit \{#uikit\} ### AdaptyPaywallController → AdaptyFlowController Kontrolcü türünü ve fabrika metodunu yeniden adlandırın: ```diff showLineNumbers - let controller = try AdaptyUI.paywallController( - with: paywallConfiguration, - delegate: self - ) + let controller = try AdaptyUI.flowController( + with: flowConfiguration, + delegate: self + ) ``` ### AdaptyPaywallControllerDelegate → AdaptyFlowControllerDelegate Protokolü yeniden adlandırın ve her metot imzasını güncelleyin. `didSelectProduct` artık kaldırılan `AdaptyPaywallProductWithoutDeterminingOffer` yerine `AdaptyPaywallProduct` alıyor; `didFinishPurchase` ise [artık zorunlu olarak uygulanmalıdır](#didfinishpurchase-is-now-required) — varsayılan bir implementasyonu kalmadı. ```diff showLineNumbers - class YourClass: AdaptyPaywallControllerDelegate { + class YourClass: AdaptyFlowControllerDelegate { - func paywallControllerDidAppear(_ controller: AdaptyPaywallController) { } + func flowControllerDidAppear(_ controller: AdaptyFlowController) { } - func paywallControllerDidDisappear(_ controller: AdaptyPaywallController) { } + func flowControllerDidDisappear(_ controller: AdaptyFlowController) { } - func paywallController(_ controller: AdaptyPaywallController, - didPerform action: AdaptyUI.Action) { } + func flowController(_ controller: AdaptyFlowController, + didPerform action: AdaptyUI.Action) { } - func paywallController(_ controller: AdaptyPaywallController, - didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer) { } + func flowController(_ controller: AdaptyFlowController, + didSelectProduct product: AdaptyPaywallProduct) { } - func paywallController(_ controller: AdaptyPaywallController, - didStartPurchase product: AdaptyPaywallProduct) { } + func flowController(_ controller: AdaptyFlowController, + didStartPurchase product: AdaptyPaywallProduct) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishPurchase product: AdaptyPaywallProduct, - purchaseResult: AdaptyPurchaseResult) { } + func flowController(_ controller: AdaptyFlowController, + didFinishPurchase product: AdaptyPaywallProduct, + purchaseResult: AdaptyPurchaseResult) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailPurchase product: AdaptyPaywallProduct, - error: AdaptyError) { } + func flowController(_ controller: AdaptyFlowController, + didFailPurchase product: AdaptyPaywallProduct, + error: AdaptyError) { } - func paywallControllerDidStartRestore(_ controller: AdaptyPaywallController) { } + func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishRestoreWith profile: AdaptyProfile) { } + func flowController(_ controller: AdaptyFlowController, + didFinishRestoreWith profile: AdaptyProfile) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailRestoreWith error: AdaptyError) { } + func flowController(_ controller: AdaptyFlowController, + didFailRestoreWith error: AdaptyError) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailRenderingWith error: AdaptyUIError) { } + func flowController(_ controller: AdaptyFlowController, + didReceiveError error: AdaptyUIError) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailLoadingProductsWith error: AdaptyError) -> Bool { } + func flowController(_ controller: AdaptyFlowController, + didFailLoadingProductsWith error: AdaptyError) -> Bool { } - func paywallController(_ controller: AdaptyPaywallController, - didPartiallyLoadProducts failedIds: [String]) { } + func flowController(_ controller: AdaptyFlowController, + didPartiallyLoadProducts failedIds: [String]) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, - error: AdaptyError?) { } + func flowController(_ controller: AdaptyFlowController, + didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, + error: AdaptyError?) { } } ``` ## SwiftUI \{#swiftui\} ### .paywall() modifier → .flow() \{#paywall-modifier--flow\} Modifier adını değiştirin, yapılandırma parametre adını güncelleyin ve [artık zorunlu olan](#didfinishpurchase-is-now-required) `didFinishPurchase` closure'ını ekleyin: ```diff showLineNumbers @State var flowPresented = false // rename freely — the variable name is your choice var body: some View { Text("Hello, AdaptyUI!") - .paywall( + .flow( isPresented: $flowPresented, - paywallConfiguration: paywallConfiguration, + flowConfiguration: flowConfiguration, + didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, - didFailRendering: { error in flowPresented = false } + didReceiveError: { error in flowPresented = false } ) } ``` Yeniden adlandırılan callback, `didFailRendering`'in tetiklendiği tüm render hatalarında olduğu gibi, flow script'inden gelen yeni çalışma zamanı hatalarında da (`AdaptyUIError` kodu `4105` — `.jsException` olan JavaScript istisnaları) tetiklenir. Mevcut handler gövdelerinde kod değişikliği gerekmez — yalnızca parametreyi yeniden adlandırın. ### AdaptyPaywallView → AdaptyFlowView Görünümü yeniden adlandırın, yapılandırma parametresini güncelleyin, [artık zorunlu olan](#didfinishpurchase-is-now-required) `didFinishPurchase` closure'ını ekleyin ve varsa `didSelectProduct` closure'ını güncelleyin — artık kaldırılan `AdaptyPaywallProductWithoutDeterminingOffer` yerine `AdaptyPaywallProduct` alıyor: ```diff showLineNumbers - AdaptyPaywallView( - paywallConfiguration: paywallConfiguration, - didSelectProduct: { product: AdaptyPaywallProductWithoutDeterminingOffer in /* handle */ }, + AdaptyFlowView( + flowConfiguration: flowConfiguration, + didSelectProduct: { product: AdaptyPaywallProduct in /* handle */ }, + didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, - didFailRendering: { error in /* handle the error */ } + didReceiveError: { error in /* handle the error */ } ) ``` ## AdaptyUI özel varlıklar \{#adaptyui-custom-assets\} ### AdaptyUICustomVideoAsset Mevcut her çağrı noktasını etkileyen iki değişiklik: - `.player` artık `AVQueuePlayer` yerine `AVPlayer` alıyor. - Her case'e sonda `resolution: CGSize?` parametresi eklendi. Mevcut davranışı korumak için `nil` geçin ya da video yüklenmeden önce yerleşim alanını ayırt etmesi (en-boy oranı = `width / height`) için gerçek piksel boyutunu belirtin. ```diff showLineNumbers - case file(url: URL, preview: AdaptyUICustomImageAsset?) - case remote(url: URL, preview: AdaptyUICustomImageAsset?) - case player(item: AVPlayerItem, player: AVQueuePlayer, preview: AdaptyUICustomImageAsset?) + case file(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) + case remote(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) + case player(item: AVPlayerItem, player: AVPlayer, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) ``` ## Attribution ve entegrasyon tanımlayıcıları \{#attribution-and-integration-identifiers\} ### updateAttribution(_:source:) `source` parametresi `String` yerine yeni `AdaptyAttributionSource` türünü kullanıyor; daha önce iç içe olan `AdaptyProfile.AttributionSource` ise üst düzey `AdaptyAttributionSource` olarak yeniden adlandırıldı. Önceden tanımlanmış kaynaklardan birini kullanabilir ya da başka bir kaynak için string literal geçirebilirsiniz — `AdaptyAttributionSource`, `ExpressibleByStringLiteral` protokolüne uyduğundan mevcut string literal çağrıları derlemeye devam eder. ```diff showLineNumbers - try await Adapty.updateAttribution(attribution, source: "adjust") + try await Adapty.updateAttribution(attribution, source: .adjust) ``` Önceden tanımlanmış kaynaklar: `.appleAds`, `.adjust`, `.appsflyer`, `.branch`, `.tenjin`. Kaynağı bir `String` değişkeninde tutuyorsanız şu şekilde sarmalayın: `AdaptyAttributionSource(rawValue: yourSource)`. ### setIntegrationIdentifier(_:) `setIntegrationIdentifier(key:value:)`, bir veya daha fazla `AdaptyIntegrationIdentifier` değeri alan değişken sayıda parametre kabul eden bir metotla değiştirildi. Ham string anahtarlar yerine önceden tanımlanmış fabrika metotlarını kullanın: ```diff showLineNumbers - try await Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid) + try await Adapty.setIntegrationIdentifier(.appsflyerId(uid)) ``` Tek bir çağrıda birden fazla tanımlayıcı ayarlayabilirsiniz: ```swift showLineNumbers try await Adapty.setIntegrationIdentifier( .appsflyerId(uid), .adjustDeviceId(adid) ) ``` Her eski anahtar dizesini fabrika metoduyla değiştirin: | v3 anahtarı | v4 factory | |---|---| | `"adjust_device_id"` | `.adjustDeviceId(_:)` | | `"airbridge_device_id"` | `.airbridgeDeviceId(_:)` | | `"amplitude_user_id"` | `.amplitudeUserId(_:)` | | `"amplitude_device_id"` | `.amplitudeDeviceId(_:)` | | `"appmetrica_device_id"` | `.appmetricaDeviceId(_:)` | | `"appmetrica_profile_id"` | `.appmetricaProfileId(_:)` | | `"appsflyer_id"` | `.appsflyerId(_:)` | | `"branch_id"` | `.branchId(_:)` | | `"facebook_anonymous_id"` | `.facebookAnonymousId(_:)` | | `"firebase_app_instance_id"` | `.firebaseAppInstanceId(_:)` | | `"mixpanel_user_id"` | `.mixpanelUserId(_:)` | | `"one_signal_subscription_id"` | `.oneSignalSubscriptionId(_:)` | | `"one_signal_player_id"` | `.oneSignalPlayerId(_:)` | | `"posthog_distinct_user_id"` | `.posthogDistinctUserId(_:)` | | `"pushwoosh_hwid"` | `.pushwooshHWID(_:)` | | `"tenjin_analytics_installation_id"` | `.tenjinAnalyticsInstallationId(_:)` | --- # File: migration-to-ios-315 --- --- title: "Adapty iOS SDK'yı v3.15'e Geçirin" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty iOS SDK v3.15'e geçin." --- [Paywall Builder](adapty-paywall-builder)'ı [Observer mode](observer-vs-full-mode)'da kullanıyorsanız, iOS SDK 3.15'ten itibaren yeni bir `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` metodu uygulamanız gerekiyor. Bu metot, satın alma işlemlerini geri yükleme mantığı üzerinde daha fazla kontrol sağlayarak bunları kendi özel flow'unuzda yönetmenize olanak tanır. Tam uygulama ayrıntıları için [Observer mode'da Paywall Builder paywall'larını sunma](ios-present-paywall-builder-paywalls-in-observer-mode) sayfasına bakın. ```diff showLineNumbers func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } + func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, + onFinishRestore: @escaping () -> Void) { + // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore + } ``` --- # File: migration-to-ios-sdk-34 --- --- title: "Adapty iOS SDK'yı v3.4'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.4'e geçiş yapın." --- Adapty SDK 3.4.0, büyük bir sürümdür ve sizin tarafınızda geçiş adımları gerektiren iyileştirmeler içermektedir. ## Adapty SDK aktivasyonunu güncelleme \{#update-adapty-sdk-activation\} <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```diff showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") - Adapty.activate(with: configurationBuilder) { error in + Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` **Yedek paywall dosyalarını güncelleme** Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki mevcut yedek paywallları [yeni dosyalarla değiştirin](ios-use-fallback-paywalls). </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```diff showLineNumbers @main struct SampleApp: App { init() { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") Task { - try await Adapty.activate(with: configurationBuilder) + try await Adapty.activate(with: configurationBuilder.build()) } } var body: some Scene { WindowGroup { ContentView() } } } ``` **Yedek paywall dosyalarını güncelleme** Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki mevcut yedek paywallları [yeni dosyalarla değiştirin](ios-use-fallback-paywalls). </TabItem> </Tabs> --- # File: migration-to-ios330 --- --- title: "Adapty iOS SDK'yı v3.3'e Taşıyın" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.0, bazı iyileştirmeler getiren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. `Adapty.Configuration`'ı `AdaptyConfiguration` olarak yeniden adlandırın. 2. `getViewConfiguration` metodunu `getPaywallConfiguration` olarak yeniden adlandırın. 3. SwiftUI'dan `didCancelPurchase` ve `paywall` parametrelerini kaldırın ve `viewConfiguration` parametresini `paywallConfiguration` olarak yeniden adlandırın. 4. App Store'dan gelen promosyon içi uygulama satın almalarını işleme şeklinizi güncelleyin; `AdaptyDelegate` metodundan `defermentCompletion` parametresini kaldırın. 5. `getProductsIntroductoryOfferEligibility` metodunu kaldırın. 6. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. 7. Observer modu uygulamasını güncelleyin. <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/9Xs8d0lt_RY?si=xvWhUO2tlG1tKP5f" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen> </iframe> </div> ## Adapty.Configuration'ı AdaptyConfiguration Olarak Yeniden Adlandırın \{#rename-adaptyconfiguration-to-adaptyconfiguration\} Adapty iOS SDK aktivasyon kodunu aşağıdaki şekilde güncelleyin: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```diff showLineNumbers // In your AppDelegate class: let configurationBuilder = - Adapty.Configuration + AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) .with(customerUserId: "YOUR_USER_ID") .with(idfaCollectionDisabled: false) .with(ipAddressCollectionDisabled: false) Adapty.activate(with: configurationBuilder) { error in // handle the error } ``` </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```diff showLineNumbers @main struct SampleApp: App { init() let configurationBuilder = - Adapty.Configuration + AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) // optional .with(customerUserId: "YOUR_USER_ID") // optional .with(idfaCollectionDisabled: false) // optional .with(ipAddressCollectionDisabled: false) // optional Task { try await Adapty.activate(with: configurationBuilder) } } var body: some Scene { WindowGroup { ContentView() } } } ``` </TabItem> </Tabs> ## getViewConfiguration metodunu getPaywallConfiguration olarak yeniden adlandırın \{#rename-getviewconfiguration-method-to-getpaywallconfiguration\} Paywall'ın `viewConfiguration` değerini getiren metodun adını güncelleyin: ```diff showLineNumbers guard paywall.hasViewConfiguration else { // use your custom logic return } do { - let paywallConfiguration = try await AdaptyUI.getViewConfiguration( + let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall ) // use loaded configuration } catch { // handle the error } ``` Paywall Builder kullanılarak tasarlanan paywallın görünüm yapılandırmasını getirme hakkında daha fazla bilgi için [Paywall Builder ile tasarlanan paywallın görünüm yapılandırmasını getirme](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) bölümüne bakın. ## SwiftUI'daki parametreleri güncelleme \{#change-parameters-in-swiftui\} SwiftUI'da aşağıdaki güncellemeler yapılmıştır: 1. `didCancelPurchase` parametresi kaldırıldı. Bunun yerine `didFinishPurchase` kullanın. 2. `.paywall()` metodu artık bir paywall nesnesi kabul etmiyor. 3. `paywallConfiguration` parametresi, `viewConfiguration` parametresinin yerini aldı. Kodunuzu aşağıdaki şekilde güncelleyin: ```diff showLineNumbers @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, - paywall: <paywall object>, - viewConfiguration: <LocalizedViewConfiguration>, + paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, - didFinishPurchase: { product, profile in paywallPresented = false }, + didFinishPurchase: { product, purchaseResult in /* handle the result*/ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } - didCancelPurchase: { product in /* handle the result*/} ) } ``` ## App Store'dan gelen promosyonlu uygulama içi satın almaların işlenmesini güncelleme \{#update-handling-of-promotional-in-app-purchases-from-app-store\} Aşağıdaki örnekte gösterildiği gibi, `AdaptyDelegate` metodundan `defermentCompletion` parametresini kaldırarak App Store'dan gelen promosyonlu uygulama içi satın almaların işlenme biçimini güncelleyin: ```swift showLineNumbers title="Swift" final class YourAdaptyDelegateImplementation: AdaptyDelegate { nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool { // 1a. // Return `true` to continue the transaction in your app. // 1b. // Store the product object and return `false` to defer or cancel the transaction. false } // 2. Continue the deferred purchase later on by passing the product to `makePurchase` func continueDeferredPurchase() async { let storedProduct: AdaptyDeferredProduct = // get the product object from the 1b. do { try await Adapty.makePurchase(product: storedProduct) } catch { // handle the error } } } ``` ## getProductsIntroductoryOfferEligibility metodunu kaldırın \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 öncesinde, ürün nesnesi kullanıcının uygunluğundan bağımsız olarak her zaman teklifleri içeriyordu. Teklifi kullanmadan önce uygunluğu elle kontrol etmeniz gerekiyordu. Artık ürün nesnesi yalnızca kullanıcı uygunsa teklif içeriyor. Bu, uygunluğu artık kontrol etmeniz gerekmediği anlamına geliyor — bir teklif mevcutsa kullanıcı zaten uygun demektir. Uygun olmayan kullanıcılar için teklifleri görüntülemek istiyorsanız `sk1Product` ve `sk2Product`'a başvurun. ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleyin \{#update-third-party-integration-sdk-configuration\} Adapty iOS SDK 3.3.0 ile birlikte `updateAttribution` metodunun genel API'sini güncelledik. Önceden `[AnyHashable: Any]` sözlüğü kabul ederek çeşitli servislerden attribution nesnelerini doğrudan iletmenize olanak tanıyordu. Artık `[String: any Sendable]` gerektiriyor; bu nedenle attribution nesnelerini iletmeden önce dönüştürmeniz gerekiyor. Adapty iOS SDK 3.3.0 ve sonrasında entegrasyonların düzgün çalışmasını sağlamak için aşağıdaki entegrasyonların SDK yapılandırmalarını aşağıdaki bölümlerde açıklandığı gibi güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. <Tabs groupId="current-os" queryString> <TabItem value="v5" label="Adjust 5.x+" default> ```diff showLineNumbers class AdjustModuleImplementation { - func updateAdjustAttribution() { - Adjust.attribution { attribution in - guard let attributionDictionary = attribution?.dictionary()?.toSendableDict() else { return } - - Adjust.adid { adid in - guard let adid else { return } - - Adapty.updateAttribution(attributionDictionary, source: .adjust, networkUserId: adid) { error in - // handle the error - } - } - } - } + func updateAdjustAdid() { + Adjust.adid { adid in + guard let adid else { return } + + Adapty.setIntegrationIdentifier(key: "adjust_device_id", value: adid) + } + } + + func updateAdjustAttribution() { + Adjust.attribution { attribution in + guard let attribution = attribution?.dictionary() else { + return + } + + Adapty.updateAttribution(attribution, source: "adjust") + } + } } ``` </TabItem> <TabItem value="v4" label="Adjust 4.x" default> ```diff showLineNumbers class YourAdjustDelegateImplementation { // Find your implementation of AdjustDelegate // and update adjustAttributionChanged method: func adjustAttributionChanged(_ attribution: ADJAttribution?) { - if let attribution = attribution?.dictionary()?.toSendableDict() { - Adapty.updateAttribution(attribution, source: .adjust) + if let attribution = attribution?.dictionary() { + Adapty.updateAttribution(attribution, source: "adjust") } } } ``` </TabItem> </Tabs> ### AirBridge Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için bkz. [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge). ```diff showLineNumbers import AirBridge - let builder = AdaptyProfileParameters.Builder() - .with(airbridgeDeviceId: AirBridge.deviceUUID()) - - Adapty.updateProfile(params: builder.build()) + do { + try await Adapty.setIntegrationIdentifier( + key: "airbridge_device_id", + value: AirBridge.deviceUUID() + ) + } catch { + // handle the error + } ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import Amplitude - let builder = AdaptyProfileParameters.Builder() - .with(amplitudeUserId: Amplitude.instance().userId) - .with(amplitudeDeviceId: Amplitude.instance().deviceId) - - Adapty.updateProfile(params: builder.build()) + do { + try await Adapty.setIntegrationIdentifier( + key: "amplitude_user_id", + value: Amplitude.instance().userId + ) + try await Adapty.setIntegrationIdentifier( + key: "amplitude_device_id", + value: Amplitude.instance().deviceId + ) + } catch { + // handle the error + } ``` ### AppMetrica Mobil uygulama kodunuzu aşağıdaki gibi güncelleyin. Tam kod örneği için [AppMetrica entegrasyonunda SDK yapılandırması](appmetrica#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import AppMetricaCore - if let deviceID = AppMetrica.deviceID { - let builder = AdaptyProfileParameters.Builder() - .with(appmetricaDeviceId: deviceID) - .with(appmetricaProfileId: "YOUR_ADAPTY_CUSTOMER_USER_ID") - - Adapty.updateProfile(params: builder.build()) - } + if let deviceID = AppMetrica.deviceID { + do { + try await Adapty.setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceID + ) + try await Adapty.setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID" + ) + } catch { + // handle the error + } + } ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) sayfasına bakın. ```diff showLineNumbers class YourAppsFlyerLibDelegateImplementation { // Find your implementation of AppsFlyerLibDelegate // and update onConversionDataSuccess method: func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) { let uid = AppsFlyerLib.shared().getAppsFlyerUID() - Adapty.updateAttribution( - conversionInfo.toSendableDict(), - source: .appsflyer, - networkUserId: uid - ) + Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid) + Adapty.updateAttribution(conversionInfo, source: "appsflyer") } } ``` ### Branch Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırmasına](branch#connect-your-app-to-branch) bakın. ```diff showLineNumbers class YourBranchImplementation { func initializeBranch() { // Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty. Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in - if let data = data?.toSendableDict() { - Adapty.updateAttribution(data, source: .branch) - } + if let data { + Adapty.updateAttribution(data, source: "branch") + } } } } ``` ### Facebook Ads Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Facebook Ads entegrasyonu için SDK yapılandırması](facebook-ads#connect-your-app-to-facebook-ads) bölümüne bakın. ```diff showLineNumbers import FacebookCore - let builder = AdaptyProfileParameters.Builder() - .with(facebookAnonymousId: AppEvents.shared.anonymousID) - - do { - try Adapty.updateProfile(params: builder.build()) - } catch { - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "facebook_anonymous_id", + value: AppEvents.shared.anonymousID + ) + } catch { + // handle the error + } ``` ### Firebase ve Google Analytics \{#firebase-and-google-analytics\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers import FirebaseCore import FirebaseAnalytics FirebaseApp.configure() - if let appInstanceId = Analytics.appInstanceID() { - let builder = AdaptyProfileParameters.Builder() - .with(firebaseAppInstanceId: appInstanceId) - Adapty.updateProfile(params: builder.build()) { error in - // handle error - } - } + if let appInstanceId = Analytics.appInstanceID() { + do { + try await Adapty.setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId + ) + } catch { + // handle the error + } + } ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonunda SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import Mixpanel - let builder = AdaptyProfileParameters.Builder() - .with(mixpanelUserId: Mixpanel.mainInstance().distinctId) - - do { - try await Adapty.updateProfile(params: builder.build()) - } catch { - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "mixpanel_user_id", + value: Mixpanel.mainInstance().distinctId + ) + } catch { + // handle the error + } ``` ### OneSignal Aşağıda gösterildiği şekilde mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) sayfasına bakın. ```diff showLineNumbers // PlayerID (pre-v5 OneSignal SDK) // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { - let params = AdaptyProfileParameters.Builder() - .with(oneSignalPlayerId: playerId) - .build() - - Adapty.updateProfile(params:params) { error in - // check error - } + Task { + try await Adapty.setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId + ) + } } } // SubscriptionID (v5+ OneSignal SDK) OneSignal.Notifications.requestPermission({ accepted in - let id = OneSignal.User.pushSubscription.id - - let builder = AdaptyProfileParameters.Builder() - .with(oneSignalSubscriptionId: id) - - Adapty.updateProfile(params: builder.build()) + Task { + try await Adapty.setIntegrationIdentifier( + key: "one_signal_subscription_id", + value: OneSignal.User.pushSubscription.id + ) + } }, fallbackToSettings: true) ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonunun SDK yapılandırması](pushwoosh#sdk-configuration) sayfasına bakın. ```diff showLineNumbers - let params = AdaptyProfileParameters.Builder() - .with(pushwooshHWID: Pushwoosh.sharedInstance().getHWID()) - .build() - - Adapty.updateProfile(params: params) { error in - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: Pushwoosh.sharedInstance().getHWID() + ) + } catch { + // handle the error + } ``` ## Observer mode implementasyonunu güncelleme \{#update-observer-mode-implementation\} Paywall'ları işlemlerle nasıl ilişkilendirdiğinizi güncelleyin. Önceden, `variationId` atamak için `setVariationId` metodunu kullanıyordunuz. Artık `variationId`'yi, yeni `reportTransaction` metodunu kullanarak işlemi kaydederken doğrudan ekleyebilirsiniz. Nihai kod örneğine [Observer mode'da paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode) bölümünden bakabilirsiniz. :::warning İşlemi `reportTransaction` metoduyla kaydetmeyi unutmayın. Bu adımı atlarsanız Adapty işlemi tanımaz, access level vermez, analitiklere eklemez veya entegrasyonlara göndermez. Bu adım zorunludur! ::: ```diff showLineNumbers - let variationId = paywall.variationId - - // There are two overloads: for StoreKit 1 and StoreKit 2 - Adapty.setVariationId(variationId, forPurchasedTransaction: transaction) { error in - if error == nil { - // successful binding - } - } + do { + // every time when calling transaction.finish() + try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) + } catch { + // handle the error + } ``` --- # File: migration-to-ios-sdk-v3 --- --- title: "Adapty iOS SDK'yı v3.0'a Geçirme" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.0'a geçiş yapın." --- Adapty SDK v3.0, yeni nesil [Adapty Paywall Builder](adapty-paywall-builder)'ı destekler; bu, paywall oluşturmak için tasarlanmış, kod gerektirmeyen kullanıcı dostu aracın yeni sürümüdür. Maksimum esnekliği ve zengin tasarım özellikleriyle paywalllarınız çok daha etkili ve kârlı hale gelecektir. :::info AdaptyUI kütüphanesinin artık kullanımdan kaldırıldığını ve AdaptySDK'nın bir parçası olarak dahil edildiğini lütfen unutmayın. ::: ## Adapty SDK v3.x'i Swift Package Manager ile Yeniden Yükleme \{#reinstall-adapty-sdk-v3x-via-swift-package-manager\} 1. AdaptyUI SDK paket bağımlılığını projenizden silin, artık ihtiyacınız olmayacak. 2. Adapty SDK bağımlılığını zaten eklemiş olsanız da yeniden eklemeniz gerekecek. Bunun için Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme yöntemi Xcode sürümüne göre farklılık gösterebilir. Gerekirse Xcode belgelerine başvurun. 3. Depo URL'sini girin: `https://github.com/adaptyteam/AdaptySDK-iOS.git` 4. Sürümü seçin ve **Add package** düğmesine tıklayın. 5. İhtiyacınız olan modülleri seçin: 1. **Adapty** zorunlu modüldür 2. **AdaptyUI**, [Adapty Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ihtiyaç duyacağınız isteğe bağlı modüldür. 6. Xcode paketi projenize ekleyecek ve içe aktarabileceksiniz. Bunun için **Choose Package Products** penceresinde **Add package** düğmesine bir kez daha tıklayın. Paket, **Packages** listesinde görünecektir. ## CocoaPods ile Adapty SDK v3.x'i Yeniden Yükleme \{#reinstall-adapty-sdk-v3x-via-cocoapods\} 1. `Podfile` dosyanıza Adapty'yi ekleyin. İhtiyacınız olan modülleri seçin: 1. **Adapty** zorunlu modüldür. 2. **AdaptyUI**, [Adapty Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ihtiyaç duyacağınız isteğe bağlı modüldür. 2. ```shell showLineNumbers title="Podfile" pod 'Adapty', '~> 3.2.0' pod 'AdaptyUI', '~> 3.2.0' # optional module needed only for Paywall Builder ``` 3. Çalıştırın: ```sh showLineNumbers title="Shell" pod install ``` Bu işlem uygulamanız için bir `.xcworkspace` dosyası oluşturur. Uygulamanızın tüm geliştirme süreçlerinde bu dosyayı kullanın. Adapty ve AdaptyUI SDK modüllerini etkinleştirin. v3.0 öncesinde AdaptyUI'yi etkinleştirmiyordunuz; **AdaptyUI aktivasyonunu eklemeyi** unutmayın. Parametreler değişmediğinden olduğu gibi bırakabilirsiniz. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .Builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) .with(customerUserId: "YOUR_USER_ID") .with(idfaCollectionDisabled: false) .with(ipAddressCollectionDisabled: false) Adapty.activate(with: configurationBuilder) { error in // handle the error } // Only if you are going to use AdaptyUI AdaptyUI.activate() ``` </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```swift title="" showLineNumbers @main struct SampleApp: App { init() let configurationBuilder = AdaptyConfiguration .Builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) // optional .with(customerUserId: "YOUR_USER_ID") // optional .with(idfaCollectionDisabled: false) // optional .with(ipAddressCollectionDisabled: false) // optional Adapty.activate(with: configurationBuilder) { error in // handle the error } // Only if you are going to use AdaptyUI AdaptyUI.activate() } var body: some Scene { WindowGroup { ContentView() } } } ``` </TabItem> </Tabs> --- # End of Documentation _Generated on: 2026-07-24T13:02:34.349Z_ _Successfully processed: 44/44 files_ # KMP - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.352Z Total files: 48 --- # File: kmp-sdk-overview --- --- title: "Kotlin Multiplatform SDK'ya Genel Bakış" description: "Adapty Kotlin Multiplatform SDK'sı ve temel özellikleri hakkında bilgi edinin." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-KMP.svg?style=flat&logo=kotlin)](https://github.com/adaptyteam/AdaptySDK-KMP/releases) Hoş geldiniz! Uygulama içi satın almaları kolaylaştırmak için buradayız 🚀 Adapty Kotlin Multiplatform SDK'sını, uygulama içi satın alma dertlerini ortadan kaldırıp sizi en iyi yaptığınız şeye odaklanmanız için geliştirdik: harika uygulamalar yaratmak. İşte sizin adınıza üstlendiğimiz işler: - Satın almaları, makbuz doğrulamayı ve abonelik yönetimini hazır olarak sunuyoruz - Uygulama güncellemesi gerektirmeden paywall oluşturun ve test edin - Sıfır kurulumla ayrıntılı satın alma analitiği edinin — kohort, LTV, churn ve dönüşüm hunisi analizi dahil - Uygulama oturumları ve cihazlar arasında kullanıcı abonelik durumunu her zaman güncel tutun - Uygulamanızı tek bir satır kodla pazarlama attribution ve analitik hizmetleriyle entegre edin :::note Koda dalmadan önce Adapty'yi Google Play Console ile entegre etmeniz ve kontrol panelinde ürünleri ayarlamanız gerekir. Her şeyi önce yapılandırmak için [hızlı başlangıç rehberimize](quickstart) göz atın. ::: ## Başlarken \{#get-started\} For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. Entegrasyon rehberinde şunları ele alacağız: 1. [SDK'yı yükle ve yapılandır](sdk-installation-kotlin-multiplatform): SDK'yı projenize bağımlılık olarak ekleyin ve kodda etkinleştirin. 2. [Flow'lar aracılığıyla satın alımları etkinleştir](kmp-quickstart-paywalls): Kullanıcıların ürün satın alabilmesi için satın alma akışını kurun. Kendi kullanıcı arayüzünüzü oluşturmak için [Paywall'ları manuel olarak uygulama](kmp-quickstart-manual) bölümüne bakın. 3. [Abonelik durumunu kontrol et](kmp-check-subscription-status): Kullanıcının abonelik durumunu otomatik olarak kontrol edin ve ücretli içeriğe erişimini yönetin. 4. [Kullanıcıları tanımla (isteğe bağlı)](kmp-quickstart-identify): Kullanıcıları Adapty profilleriyle ilişkilendirerek verilerinin cihazlar arasında tutarlı biçimde saklanmasını sağlayın. ### Nasıl çalıştığını görün \{#see-it-in-action\} Her şeyin nasıl bir araya geldiğini görmek ister misiniz? - **Örnek uygulama**: Tam kurulumu gösteren [eksiksiz örneğimize](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) göz atın - **Video eğitimi**: Aşağıdaki adım adım uygulama videomuzla birlikte ilerleyin <iframe width="560" height="315" src="https://www.youtube.com/embed/JfwJvwnloNw?si=HskPxRk4WGkF_u9s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ## Temel kavramlar \{#main-concepts\} Koda dalmadan önce Adapty'nin nasıl çalıştığını anlamak için temel kavramlara göz atalım. Adapty yaklaşımının güzelliği şu: uygulamanızda yalnızca placement'lar sabit kodlanır. Geri kalan her şey — ürünler, paywall tasarımları, fiyatlandırma ve teklifler — uygulama güncellemesi gerekmeksizin Adapty kontrol panelinden esnek biçimde yönetilebilir: 1. [**Ürün**](product) - Uygulamanızda satın alınabilecek her şey: abonelik, consumable ürün veya süresiz erişim. 2. **Flow veya paywall** - Bir placement'a bağlı, yapılandırmayla paketlenmiş ürünler. İki türü vardır: - **[Flow](adapty-flow-builder)** - Flow Builder'da oluşturulmuş, görsel ve kodsuz arayüz. Adapty kullanıcı arayüzünü render eder ve satın almayı sizin adınıza yönetir. - **[Paywall](paywalls)** - Görsel yapılandırma yoktur; kullanıcı arayüzünü kendi kodunuzda oluşturur ve `makePurchase`'ı kendiniz çağırırsınız. Bkz. [Paywall'ları manuel olarak uygulama](kmp-quickstart-manual). SDK kodunda her ikisi de aynı `getFlow` yöntemiyle alınır. 3. [**Placement**](placements) - Kullanıcı yolculuğunuzda bir flow veya paywall göstermek istediğiniz stratejik nokta. Placement'ları para kazanma stratejinizin "nerede" ve "ne zaman"ı olarak düşünebilirsiniz. Yaygın placement'lar şunlardır: - `main` - Birincil paywall konumunuz - `onboarding` - Kullanıcı onboarding flow'u sırasında gösterilen - `settings` - Uygulamanızın ayarlarından erişilebilen İlk entegrasyonunuz için `main` veya `onboarding` gibi temel olanlarla başlayın, ardından [uygulamanızda kullanıcıların satın almaya hazır olabileceği diğer yerleri düşünün](choose-meaningful-placements). 4. [**Profil**](profiles-crm) - Kullanıcılar bir ürün satın aldığında, profillerine bir **access level** atanır; bu access level'ı ücretli özelliklere erişimi tanımlamak için kullanırsınız. --- # File: sdk-installation-kotlin-multiplatform --- --- title: "Adapty Kotlin Multiplatform SDK'yı Yükleyin ve Yapılandırın" description: "Kotlin Multiplatform uygulamaları için Adapty SDK'yı yükleyin ve yapılandırın." --- Adapty SDK, mobil uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI** (`io.adapty:adapty-kmp-ui`): Bu modül, Compose Multiplatform render katmanıyla (`view.present()`) [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız gereklidir. Projeniz Compose Multiplatform kullanmıyorsa, bunun yerine core modülündeki [`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform) ve [`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform) kullanabilirsiniz. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek bir örnek görmek ister misiniz? Kurulumun tamamını, paywall gösterimi, satın alma işlemleri ve diğer temel işlevleri içeren [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) göz atın. ::: Eksiksiz bir uygulama adım adım anlatımı için videoyu da izleyebilirsiniz: <iframe width="560" height="315" src="https://www.youtube.com/embed/JfwJvwnloNw?si=HskPxRk4WGkF_u9s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ## Gereksinimler \{#requirements\} Adapty Kotlin Multiplatform SDK, Xcode 16.2 ve sonraki sürümlerle uyumludur. :::info Adapty, Google Play Billing Library 8.x sürümüne kadar uyumludur. Adapty varsayılan olarak Google Play Billing Library v.7.0.0 ile çalışır; ancak daha yeni bir sürüm kullanmak istiyorsanız [bağımlılığı](https://developer.android.com/google/play/billing/integrate#dependency) manuel olarak ekleyebilirsiniz. ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Gradle ile Yükleyin \{#install-adapty-sdk-via-gradle\} Adapty SDK'yı Gradle ile yüklemek hem Android hem de iOS uygulamaları için gereklidir. Bağımlılık kurulum yöntemini seçin: - Standart Gradle: Bağımlılıkları **modül düzeyindeki** `build.gradle` dosyanıza ekleyin - Projeniz `.gradle.kts` dosyaları kullanıyorsa, bağımlılıkları **modül düzeyindeki** `build.gradle.kts` dosyanıza ekleyin - Sürüm katalogları kullanıyorsanız, bağımlılıkları `libs.versions.toml` dosyanıza ekleyin ve ardından `build.gradle.kts` içinde referans verin :::important Adapty Kotlin Multiplatform SDK 4.0 ön sürümdür. Gradle, dinamik sürüm aralıkları (`+` veya `latest.release` gibi) aracılığıyla ön sürümleri seçmez; bu nedenle tam sürümü sabitlemeniz gerekir — örneğin `io.adapty:adapty-kmp:4.0.0-beta.1` veya `libs.versions.toml` dosyasında `adapty-kmp = "4.0.0-beta.1"`. Bakınız [Adapty Kotlin Multiplatform SDK'yı v4'e Taşıma](migration-to-kmp-sdk-v4). ::: <Tabs> <TabItem value="module-level build.gradle" label="module-level build.gradle" default> ```kotlin showLineNumbers kotlin { sourceSets { commonMain { dependencies { implementation libs.adapty.kmp } } } } ``` </TabItem> <TabItem value="module-level build.gradle.kts" label="module-level build.gradle.kts" default> ```kotlin showLineNumbers kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` </TabItem> <TabItem value="version-catalog" label="Sürümler kütüphanesi" default> ```toml showLineNumbers // libs.versions.toml [versions] .. adapty-kmp = "<the latest SDK version>" [libraries] .. adapty-kmp = { module = "io.adapty:adapty-kmp", version.ref = "adapty-kmp" } // build.gradle.kts kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` </TabItem> </Tabs> :::note Maven ile ilgili bir hata alırsanız, Gradle scriptlerinizde `mavenCentral()` bulunduğundan emin olun. <details> <summary>Nasıl ekleneceğine dair talimat</summary> Projenizde `settings.gradle` dosyasında `dependencyResolutionManagement` yoksa, en üst düzey `build.gradle` dosyanızın repositories bölümünün sonuna şunları ekleyin: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` Aksi takdirde, `settings.gradle` dosyanızdaki `dependencyResolutionManagement` bölümünün `repositories` kısmına şunları ekleyin: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... google() mavenCentral() } } ``` </details> ::: ## Adapty SDK'yı etkinleştirin \{#activate-adapty-sdk\} ### Temel kurulum \{#basic-setup\} Başlatma işlemini mümkün olduğunca erken ekleyin; genellikle her iki platform için de paylaşılan Kotlin kodunuzda yapılır. :::note Adapty SDK, uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` :::important Herhangi bir Adapty SDK metodunu çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıra için [Kotlin Multiplatform SDK'da çağrı sırası](kmp-sdk-call-order) bölümüne bakın. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [App settings → General](https://app.adapty.io/settings/general) bölümüne gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini bu anahtarla değiştirin. :::info - Adapty başlatma işlemi için Public SDK anahtarını kullandığınızdan emin olun; Secret anahtar yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - SDK anahtarları her uygulama için benzersizdir; birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. ::: Şimdi uygulamanızda paywall'ları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](kmp-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywall'lar için hızlı başlangıç kılavuzuna](kmp-quickstart-manual) bakın. ## AdaptyUI modülünü etkinleştirme \{#activate-adaptyui-module-of-adapty-sdk\} [Adapty Paywall Builder](kmp-present-paywalls) kullanımı için **AdaptyUI** modülünü etkinleştirmeyi planlıyorsanız, yapılandırmanızda `.withActivateUI(true)` ayarını yapmayı unutmayın. :::info önemli Kodunuzda, AdaptyUI'ı etkinleştirmeden önce çekirdek Adapty modülünü etkinleştirmeniz gerekir. ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withActivateUI(true) // true for activating the AdaptyUI module .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` ## Proguard'ı yapılandırın (Android) \{#configure-proguard-android\} Uygulamanızı production'a almadan önce Proguard yapılandırmanıza `-keep class com.adapty.** { *; }` eklemeniz gerekebilir. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlükleme \{#logging\} #### Günlükleme sistemini yapılandırma \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki seviyeleri kullanabilirsiniz: | Seviye | Açıklama | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | `AdaptyLogLevel.ERROR` | Yalnızca hatalar loglanır. | | `AdaptyLogLevel.WARN` | Hatalar ve kritik hatalara yol açmayan ancak dikkat edilmesi gereken SDK mesajları loglanır. | | `AdaptyLogLevel.INFO` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır. Varsayılan değer. | | `AdaptyLogLevel.VERBOSE` | Hata ayıklama sırasında işe yarayabilecek ek bilgiler (fonksiyon çağrıları, API sorguları vb.) loglanır. | | `AdaptyLogLevel.DEBUG` | İç debug verileri dahil olmak üzere en ayrıntılı bilgiler loglanır. | Adapty'yi yapılandırmadan önce uygulamanızda log seviyesini ayarlayabilirsiniz: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withLogLevel(AdaptyLogLevel.VERBOSE) // recommended for development .build() ``` ### Veri politikaları \{#data-policies\} #### IP adresi toplama ve paylaşımını devre dışı bırak \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; kullanıcı gizliliğini artırmak, bölgesel veri koruma yönetmeliklerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özellikler uygulamanız için gerekli değilse gereksiz veri toplamayı azaltmak amacıyla kullanabilirsiniz. ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` #### Reklam ID'si toplama ve paylaşmayı devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `appleIdfaCollectionDisabled` (iOS) veya `googleAdvertisingIdCollectionDisabled` (Android) değerini true olarak ayarlayın. Varsayılan değer false'tur. App Store/Play Store politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak veya uygulamanız reklam kimliklerine dayalı reklam attribution ya da analitik gerektirmiyorsa bu parametreyi kullanın. ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleAdvertisingIdCollectionDisabled(true) // Android only .withAppleIdfaCollectionDisabled(true) // iOS only .build() ``` #### AdaptyUI için medya önbelleği yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} Varsayılan olarak AdaptyUI, performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) önbelleğe alır. Önbellek ayarlarını özel bir yapılandırma sağlayarak özelleştirebilirsiniz. Varsayılan önbellek ayarlarını geçersiz kılmak için `mediaCache` kullanın: ```kotlin val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withMediaCacheConfiguration( AdaptyConfig.MediaCacheConfiguration( memoryStorageTotalCostLimit = 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit = Int.MAX_VALUE, diskStorageSizeLimit = 200 * 1024 * 1024 // 200 MB ) ) .build() ``` ### Yerel access level'ları etkinleştirin (Android) \{#enable-local-access-levels-android\} Varsayılan olarak [yerel access level'lar](local-access-levels) Android için devre dışıdır. Etkinleştirmek için `withLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleLocalAccessLevelAllowed(true) .build() ``` ### Yedekten geri yüklemede verileri temizle \{#clear-data-on-backup-restore\} `withAppleClearDataOnBackup` değeri `true` olarak ayarlandığında, SDK uygulamanın iCloud yedeklemesinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywalllar dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```swift showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withAppleClearDataOnBackup(true) .build() ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Auto Backup yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::important Kotlin Multiplatform projesinde, bu değişiklikleri APK/AAB üreten Android uygulama modülüne (örneğin `androidApp` veya `app`) uygulayın: - Manifest: `androidApp/src/main/AndroidManifest.xml` - Yedekleme kuralları XML: `androidApp/src/main/res/xml/` ::: #### Android'de başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} Satın alma flow'unu başlatan Activity varsayılan olmayan bir `launchMode` kullanıyorsa, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan geri döndüğünde Android bu Activity'yi hatalı şekilde yeniden oluşturabilir veya yeniden kullanabilir. Bu durum, satın alma sonucunun kaybolmasına veya iptal edilmiş gibi işlenmesine neden olabilir. Satın almaların doğru çalışmasını sağlamak için, satın alma flow'unu başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın; diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma flow'unu başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` --- # File: kmp-quickstart-paywalls --- --- title: "Kotlin Multiplatform SDK'da Flow Builder ile satın almaları etkinleştirme" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmek için hızlı başlangıç kılavuzu." --- Bu kılavuz, Adapty Kotlin Multiplatform SDK v4 (beta) API'lerini kullanmaktadır. v3 kullanıyorsanız, ilgili metod adları için [geçiş kılavuzuna](migration-to-kmp-sdk-v4) bakın. Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – no-code Flow Builder ile oluşturulan, kullanıcılara ürünleri sunan ekran dizileri. SDK bunları `getFlow` aracılığıyla getirir. Kullanıcı arayüzünü kendi kodunuzda oluşturmayı tercih ederseniz, bunun yerine bir paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](kmp-quickstart-manual). - [**Placement'lar**](placements) – uygulamanızda flow'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'si ile talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek kolaylaşır. Adapty, uygulamanızda satın alımları etkinleştirmek için üç yol sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | No-code builder'da [eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm karmaşık satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda halleder. | | Elle oluşturulan paywalllar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine de Adapty'den alırsınız. [Rehbere](kmp-quickstart-manual) bakın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı kısıtlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulmuş bir flow'un nasıl uygulanacağını göstermektedir.** Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, bkz. [Paywallları manuel olarak uygulama](kmp-quickstart-manual). ::: Adapty Flow Builder'da oluşturulmuş bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Adapty'den alın. 2. **Görüntüleyin; satın alma işlemlerini Adapty sizin için yönetir**: Görünümü uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butonlara tıkladığında bağlantı açın veya flow'u kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Uygulamanızı Adapty Kontrol Paneli'nde [App Store](initial_ios) ve/veya [Google Play](initial-android) ile bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve buna ürün ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'u buna ekleyin](create-placement). 5. Uygulama kodunuza [Adapty SDK'yı yükleyip etkinleştirin](sdk-installation-kotlin-multiplatform). :::tip Bu adımları tamamlamanın en hızlı yolu [hızlı başlangıç kılavuzunu](quickstart) takip etmek veya [Developer CLI](developer-cli-quickstart) kullanarak flow'lar ve placement'lar oluşturmaktır. ::: ## 1. Flow'u alın \{#1-get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılan placement'larla ilişkilidir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty Flow Builder'da oluşturulmuş bir flow'u almak için şunları yapmanız gerekir: 1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın. 2. `createFlowView` metodunu kullanarak flow view'ını oluşturun. View, flow'u görüntülemek için gereken UI öğelerini ve stilini içerir. Flow'da yapılandırılmış bir view yoksa `createFlowView` hata döndürür — bunu `onError` içinde ele alın. :::important Görünümü almak için Flow Builder'da **Show on device** geçişini açmanız gerekir. Aksi takdirde, `createFlowView` bir hata döndürecek ve flow görüntülenmeyecektir. ::: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") .onSuccess { flow -> AdaptyUI.createFlowView(flow) .onSuccess { view -> view.present() } .onError { error -> // the flow has no view configured, or view creation failed } } .onError { error -> // handle the error } ``` ## 2. Flow'u görüntüleme \{#display-the-flow\} Artık flow'a sahip olduğunuzda, onu görüntülemek için birkaç satır eklemek yeterlidir. Görsel flow'u cihaz ekranında göstermek için önce view'ı oluşturmanız gerekir. Bunun için `AdaptyUI.createFlowView()` metodunu çağırın: ```kotlin showLineNumbers AdaptyUI.createFlowView(flow) .onSuccess { view -> view.present() } .onError { error -> // handle the error } ``` Görünüm başarıyla oluşturulduktan sonra cihaz ekranında gösterebilirsiniz. Her görünüm yalnızca bir kez kullanılabilir: `dismiss()` çağrısından sonra flow'u tekrar göstermek için `createFlowView` fonksiyonunu tekrar çağırmanız gerekir. :::tip Bir flow'un nasıl görüntüleneceğine ilişkin daha fazla ayrıntı için [kılavuzumuza](kmp-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetme \{#handle-button-actions\} Kullanıcılar flow içindeki butonlara tıkladığında, Kotlin Multiplatform SDK satın alma işlemlerini, geri yüklemeyi, flow'u kapatmayı ve bağlantı açmayı otomatik olarak yönetir. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve kodunuzda eylem yönetimi gerektirir. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, kapat butonu için varsayılan davranış şöyle görünür. Bunu koda eklemeniz gerekmez, ancak burada gerektiğinde nasıl yapıldığını görebilirsiniz. Varsayılan olarak, başarılı bir satın alma işleminin ardından flow açık kalmaya devam eder. Satın alma tamamlandığında flow'u kapatmak istiyorsanız, görünümü `flowViewDidFinishPurchase` callback'inde dismiss edin. :::tip Buton [action](kmp-handle-paywall-actions)'larını ve [event](kmp-handling-events)'leri nasıl yöneteceğinizi anlatan kılavuzlarımızı okuyun. ::: ```kotlin showLineNumbers AdaptyUI.setFlowsEventsObserver(object : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> mainUiScope.launch { view.dismiss() } else -> Unit } } override fun flowViewDidFinishPurchase( view: AdaptyUIFlowView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { if (purchaseResult !is AdaptyPurchaseResult.UserCanceled) { mainUiScope.launch { view.dismiss() } } } }) ``` ## Sonraki adımlar \{#next-steps\} Flow'unuz uygulamada görüntülenmeye hazır. Bir test satın alımını flow üzerinden tamamlayabildiğinizden emin olmak için [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android) üzerinde satın alımlarınızı test edin. Şimdi, doğru kullanıcılara flow gösterdiğinizden veya ücretli özelliklere erişim verdiğinizden emin olmak için [kullanıcıların access level'ını kontrol etmeniz](kmp-check-subscription-status) gerekiyor. ## Tam örnek \{#full-example\} Tüm bu adımların uygulamanızda birlikte nasıl entegre edilebileceği aşağıda gösterilmektedir. ```kotlin showLineNumbers // Set up the observer for handling flow events AdaptyUI.setFlowsEventsObserver(object : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> mainUiScope.launch { view.dismiss() } else -> Unit } } override fun flowViewDidFinishPurchase( view: AdaptyUIFlowView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { if (purchaseResult !is AdaptyPurchaseResult.UserCanceled) { mainUiScope.launch { view.dismiss() } } } }) // Get and display the flow Adapty.getFlow("YOUR_PLACEMENT_ID") .onSuccess { flow -> AdaptyUI.createFlowView(flow) .onSuccess { view -> view.present() } .onError { error -> // the flow has no view configured — use custom logic } } .onError { error -> // handle the error } ``` --- # File: kmp-check-subscription-status --- --- title: "Kotlin Multiplatform SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Kotlin Multiplatform uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) bilgisini kontrol etmeniz gerekir. Bu makalede, kullanıcılara paywall mı yoksa premium içerik mi gösterileceğine karar vermek amacıyla profil durumuna nasıl erişeceğiniz anlatılmaktadır. ## Abonelik durumunu alma \{#get-subscription-status\} Kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profildeki [access level](access-level) bilgisini kontrol edersiniz. İki seçeneğiniz var: - En güncel profil verilerine hemen ihtiyaç duyduğunuzda (örneğin uygulama açılışında) veya bir güncellemeye zorlamak istediğinizde `getProfile` çağırın. - Abonelik durumu değiştiğinde otomatik olarak güncellenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** etkinleştirin. ### Profili alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, `getProfile` metodunu kullanarak profile erişmektir: ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access } .onError { error -> // handle the error } ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek üzere `Adapty.setOnProfileUpdatedListener()` kullanın; kullanıcının abonelik durumu her değiştiğinde Adapty bu metodu otomatik olarak çağırır. 2. Ek ağ istekleri yapmadan uygulama genelinde kullanabilmek için bu metod çağrıldığında güncel profil verilerini saklayın. ```kotlin showLineNumbers class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true } } ``` :::note Adapty, uygulama başladığında profil güncelleme dinleyicisini otomatik olarak çağırarak cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sağlar. ::: ## Profili paywall mantığıyla ilişkilendirme \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim verme konusunda anlık kararlar almanız gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girilmesi veya belirli içeriklerin gösterilmesinden önce gibi senaryolar için kullanışlıdır. ```kotlin showLineNumbers private fun checkAccessAndShowPaywall() { // First, check if user has access Adapty.getProfile() .onSuccess { profile -> val hasAccess = profile.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true if (!hasAccess) { // User doesn't have access, show paywall showPaywall() } else { // User has access, show premium content showPremiumContent() } } .onError { error -> // If we can't check access, show paywall as fallback showPaywall() } } private fun showPaywall() { // Get and display paywall using the KMP SDK Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (paywall.hasViewConfiguration) { val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } else { // Handle remote config paywall or show custom UI handleRemoteConfigPaywall(paywall) } } .onError { error -> // Handle paywall loading error showError("Unable to load paywall") } } private fun showPremiumContent() { // Show your premium content here // This is where you unlock paid features } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların satın aldıkları içeriklere erişebildiğinden emin olmak için [kullanıcı profilleriyle nasıl çalışılacağını](kmp-quickstart-identify) öğrenin. --- # File: kmp-quickstart-identify --- --- title: "Kotlin Multiplatform SDK'da kullanıcıları tanımlama" description: "KMP'de uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa sizin içindir. Burada, Adapty'deki kullanıcı profillerini mevcut kimlik doğrulama sisteminizle uyumlu hâle getirmek için nasıl çalışacağınızı öğreneceksiniz. ::: Kullanıcıların satın alımlarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız backend kimlik doğrulaması kullanmıyor ve kullanıcı verisi depolamıyorsa [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanızda backend kimlik doğrulaması varsa (veya olacaksa) [tanımlanmış kullanıcılar bölümüne](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmaksızın)** veya tanımlanmış **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi kimlik doğrulama sisteminizle çapraz referanslamak için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |-------------------------|-------------------------------------------------------|-------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arasında satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar arasında aynı profil | | **Veri kalıcılığı** | Anonim kullanıcı verisi uygulama yüklemesine bağlıdır | Tanımlanmış kullanıcı verisi uygulama yüklemeleri arasında korunur | ## Anonim kullanıcılar \{#anonymous-users\} Backend kimlik doğrulamanız yoksa **uygulama kodunda kimlik doğrulamayla ilgilenmenize gerek yoktur**: 1. SDK uygulamanın ilk başlatılmasında etkinleştirildiğinde Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada herhangi bir şey satın aldığında bu satın alma **Adapty profiliyle ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihazdan** yüklediğinde Adapty, etkinleştirmede **yeni bir anonim profil oluşturur**. 4. Kullanıcı uygulamanızda daha önce satın alım yapmışsa, varsayılan olarak bu satın alımlar SDK etkinleştirildiğinde App Store'dan otomatik olarak senkronize edilir. Anonim kullanıcılarda her yüklemede yeni profil oluşturulur; ancak bu bir sorun değildir çünkü Adapty analitiğinde [yeni yükleme olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için yüklemeleri **cihaz ID'lerine göre** saymanız gerekir. Bu durumda, yeniden yüklemeler dahil bir cihazdaki her uygulama yüklemesi bir yükleme olarak sayılır. :::note Yedekten geri yüklemeler yeniden yüklemelerden farklı davranır. Varsayılan olarak, kullanıcı yedekten geri yükleme yaptığında SDK önbelleğe alınan verileri korur ve yeni profil oluşturmaz. Bu davranışı `withAppleClearDataOnBackup` ayarıyla yapılandırabilirsiniz. [Daha fazla bilgi](sdk-installation-kotlin-multiplatform#clear-data-on-backup-restore). ::: ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamada kullanıcıları tanımlamak için iki seçeneğiniz vardır: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra giriş yapıyorsa, kimlik doğruladıklarında bir customer user ID ile `identify()` çağırın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başlarken zaten bir customer user ID'niz varsa, `activate()` çağırırken onu gönderin. :::important Varsayılan olarak Adapty, şu anda başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında access level paylaşılır; yani her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Daha fazla ayrıntı için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kayıt olduktan sonra), customer user ID'lerini ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty onu otomatik olarak mevcut profille ilişkilendirir. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır. Parametreye sabit bir değer girerseniz, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir. ::: `identify` tamamlanmadan (yani `onSuccess` callback'i tetiklenmeden) başka SDK metotlarını çağırmayın. Eş zamanlı çağrılar anonim profile yönlenebilir. Bkz. [Kotlin Multiplatform SDK'da çağrı sırası](kmp-sdk-call-order). ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Her kullanıcı için benzersiz .onSuccess { // successful identify } .onError { error -> // handle the error } ``` ### SDK etkinleştirmesi sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` çağrısını ayrıca yapmak yerine `activate` metodunda gönderebilirsiniz. Customer user ID'yi bilmenize rağmen onu yalnızca etkinleştirmeden sonra ayarlıyorsanız, bu, etkinleştirme sırasında Adapty'nin yeni bir anonim profil oluşturacağı ve `identify` çağrısından sonra mevcut profile geçeceği anlamına gelir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane iletebilirsiniz. Yeni bir tane iletirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID ile ilişkilendirilir. :::note Varsayılan olarak, anonim profil oluşturmak analitik panolarını etkilemez çünkü yüklemeler cihaz ID'lerine göre sayılır. Cihaz ID'si, uygulamanın mağazadan bir cihaza tek bir yüklemesini temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bunun ilk mi yoksa tekrarlanan bir yükleme mi olduğuna ya da mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturma (SDK etkinleştirildiğinde veya çıkış yapıldığında), giriş yapma veya uygulamayı yeniden yüklemeden güncelleme ek yükleme olayları oluşturmaz. Yüklemeleri cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın. ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ### Kullanıcıları çıkış yaptırma \{#log-users-out\} Kullanıcıları çıkış yaptırmak için bir butonunuz varsa `logout` metodunu kullanın. :::important Kullanıcıları çıkış yaptırmak, kullanıcı için yeni bir anonim profil oluşturur. ::: ```kotlin showLineNumbers Adapty.logout() .onSuccess { // successful logout } .onError { error -> // handle the error } ``` :::info Kullanıcıları uygulamaya tekrar giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın almaya izin verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alım yapabiliyorsa, giriş yaptıktan sonra erişimlerini koruyacaklarından emin olmanız gerekir: 1. Çıkış yapmış bir kullanıcı satın alım yaptığında Adapty bunu anonim profil ID'siyle ilişkilendirir. 2. Kullanıcı hesabına giriş yaptığında Adapty, tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin satın alım kayıt öncesinde yapılmışsa), Adapty customer user ID'yi mevcut profille ilişkilendirir; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profille bağlantılıysa), profil değişiminden sonra gerçek access level'ı almanız gerekir. Tanımlama işleminden hemen sonra [`getProfile`](kmp-check-subscription-status) çağırabilir ya da veriler otomatik senkronize olsun diye [profil güncellemelerini dinleyebilirsiniz](kmp-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanıza uygulama içi ödeme mantığını eklediniz! Uygulama monetizasyonunuzda başarılar diliyoruz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analitik servisleriyle entegre olun - [**Özel profil özellikleri ayarlama**](kmp-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segment'ler oluşturun; böylece A/B testi başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-kmp --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi Kotlin Multiplatform uygulamanıza entegre edin" description: "Adapty SDK'yı Kotlin Multiplatform uygulamanıza uçtan uca entegre etmek için yapay zeka kodlama aracınızla adapty-sdk-integration becerisini kullanın." --- <AdaptySdkIntegrationSkill platform="Kotlin Multiplatform" /> :::important Bu özellik beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, AI aracınıza her adımı doğru belgelerle anlatan [adım adım entegrasyon kılavuzunu](adapty-cursor-kmp) takip edin. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-kmp --- --- title: "Yapay zeka desteğiyle Kotlin Multiplatform uygulamanıza Adapty entegrasyonu" description: "Cursor, Context7, ChatGPT, Claude veya diğer yapay zeka araçlarını kullanarak Kotlin Multiplatform uygulamanıza Adapty entegre etmek için adım adım rehber." --- Bu kılavuz, bir AI kodlama aracıyla Kotlin Multiplatform uygulamanıza Adapty'yi adım adım entegre etmeyi ele alır; doğru Adapty dokümanlarını doğru sırayla besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı ayarların yapılmasını gerektirir. Bunu bir LLM becerisiyle etkileşimli olarak ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Beceri yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywalllerinizi ve placementlarınızı doğrudan ayarlamasına olanak tanır — her adım için Kontrol Panelini açmanız gerekmez. Yalnızca Kontrol Panelinde [mağazalarınızı bağlamanız](integrate-payments) yeterli. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Beceri eklendikten sonra ajanınızda `/adapty-cli` komutunu çalıştırın. Her adımda sizi yönlendirecek ve mağazalarınızı bağlamak için Kontrol Panelini ne zaman açmanız gerektiğini de belirtecek. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, kod yazmadan önce bunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için arayamaz — bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Panelinde **App settings → General** bölümüne gidin. KMP uygulamanız her iki platformu da hedefliyorsa hem App Store hem de Google Play'i bağlayın. Bu, satın almaların çalışması için zorunludur. [Uygulama mağazalarını bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Panelinde **App settings → General** bölümüne gidin, ardından **API keys** bölümünü bulun. Kodda bu, Adapty yapılandırma oluşturucusuna geçirdiğiniz dizedir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Panelinde **Products** sayfasına gidin. Ürünlere kodda doğrudan başvurmazsınız — Adapty bunları paywalllar aracılığıyla sunar. [Ürün ekleyin](quickstart-products) 4. **Bir paywall ve placement oluşturun**: Adapty Kontrol Panelinde **Paywalls** sayfasında bir paywall oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID, `Adapty.getPaywall("YOUR_PLACEMENT_ID")` çağrısına geçirdiğiniz dizedir. [Paywall oluşturun](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Panelinde **Products** sayfasında her ürün için yapılandırın. Kodda `profile.accessLevels["premium"]?.isActive` içinde kontrol edilen dizedir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ücretli kullanıcılar ürüne göre farklı özelliklere erişiyorsa (örneğin `basic` plan ve `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Bu beşine sahip olunca kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodu üretebilir. ::: ### Hazır olduğunuzda yapın \{#set-up-when-ready\} Bunlar kod yazmaya başlamak için zorunlu değil, ancak entegrasyon olgunlaştıkça ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasında yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywalllar ve placementlar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasında yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonlar](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## LLM'inize Adapty dokümanları gönderin \{#feed-adapty-docs-to-your-llm\} ### Context7 kullanın (önerilen) \{#use-context7-recommended\} [Context7](https://context7.com), LLM'inize güncel Adapty dokümantasyonuna doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, sorduğunuz şeye göre doğru dokümanları otomatik olarak çeker — manuel URL yapıştırmaya gerek yoktur. Context7, **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurmak için şunu çalıştırın: ``` npx ctx7 setup ``` Bu, düzenleyicinizi algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, promptlarınızda Adapty kitaplığına başvurun: ``` Use the adaptyteam/adapty-docs library to look up how to install the Kotlin Multiplatform SDK ``` :::warning Context7, doküman bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin doğru çalıştığından emin olmak için aşağıdaki [uygulama adım adım rehberini](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Herhangi bir Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** butonuna tıklayın. Örneğin: [adapty-cursor-kmp.md](https://adapty.io/docs/tr/adapty-cursor-kmp.md). Aşağıdaki [uygulama adım adım rehberindeki](#implementation-walkthrough) her aşama, yapıştırmak için `.md` bağlantıları içeren bir "LLM'inize gönderin" bloğu içerir. Daha fazla dokümana aynı anda erişmek için aşağıdaki [dizin dosyaları ve platforma özel alt kümeler](#plain-text-doc-index-files) bölümüne bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, Adapty entegrasyonunu uygulama sırasıyla ele alır. Her aşamada LLM'inize gönderilecek dokümanlar, tamamlandığında görmeniz gerekenler ve yaygın sorunlar yer alır. ### Entegrasyonunuzu planlayın \{#plan-your-integration\} Koda geçmeden önce LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. Yapay zeka aracınız bir planlama modunu destekliyorsa (Cursor veya Claude Code'un plan modu gibi), LLM'in herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, takip etmesi gereken rehberleri etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Paywallları Adapty'nin kodsuz oluşturucusunda oluşturursunuz ve SDK bunları otomatik olarak işler. - [**Manuel oluşturulan paywalllar**](kmp-making-purchases): Kendi paywall arayüzünüzü kodda oluşturursunuz ancak ürünleri almak ve satın almaları işlemek için yine de Adapty kullanırsınız. - [**Gözlemci modu**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosuna](kmp-quickstart-paywalls) bakın. ### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\} Adapty SDK bağımlılığını Gradle aracılığıyla ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu temeldir — geri kalan hiçbir şey bunu olmadan çalışmaz. **Rehber:** [Adapty SDK'yı yükle ve yapılandır](sdk-installation-kotlin-multiplatform) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-kotlin-multiplatform.md ``` :::tip[Kontrol noktası] - **Beklenen:** Uygulama derlenir ve çalışır. Logcat (Android) veya Xcode konsolu (iOS) Adapty etkinleştirme günlüğünü gösterir. - **Dikkat:** "Public API key is missing" → yer tutucuyu App settings'ten aldığınız gerçek anahtarla değiştirdiğinizi kontrol edin. ::: ### Paywallları gösterin ve satın almaları yönetin \{#show-paywalls-and-handle-purchases\} Placement ID ile bir paywall çekin, görüntüleyin ve satın alma olaylarını yönetin. İhtiyacınız olan rehberler, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerlerken sandbox'ta test edin — sona bırakmayın. Kurulum talimatları için [Sandbox'ta satın almaları test edin](test-purchases-in-sandbox) bölümüne bakın. <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **Rehberler:** - [Paywallları kullanarak satın almaları etkinleştirin (hızlı başlangıç)](kmp-quickstart-paywalls) - [Paywall Builder paywalllarını ve yapılandırmalarını çekin](kmp-get-pb-paywalls) - [Paywallları görüntüleyin](kmp-present-paywalls) - [Paywall olaylarını yönetin](kmp-handling-events) - [Buton eylemlerine yanıt verin](kmp-handle-paywall-actions) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/kmp-quickstart-paywalls.md - https://adapty.io/docs/tr/kmp-get-pb-paywalls.md - https://adapty.io/docs/tr/kmp-present-paywalls.md - https://adapty.io/docs/tr/kmp-handling-events.md - https://adapty.io/docs/tr/kmp-handle-paywall-actions.md ``` :::tip[Kontrol noktası] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle görünür. Bir ürüne dokunmak sandbox satın alma diyalogunu tetikler. - **Dikkat:** Boş paywall veya `getPaywall` hatası → placement ID'nin kontrol paneliyle tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manuel paywalllar"> **Rehberler:** - [Özel paywallınızda satın almaları etkinleştirin (hızlı başlangıç)](kmp-quickstart-manual) - [Paywallları ve ürünleri çekin](fetch-paywalls-and-products-kmp) - [Remote config ile tasarlanan paywallı işleyin](present-remote-config-paywalls-kmp) - [Satın alma yapın](kmp-making-purchases) - [Satın almaları geri yükleyin](kmp-restore-purchase) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/kmp-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-kmp.md - https://adapty.io/docs/tr/present-remote-config-paywalls-kmp.md - https://adapty.io/docs/tr/kmp-making-purchases.md - https://adapty.io/docs/tr/kmp-restore-purchase.md ``` :::tip[Kontrol noktası] - **Beklenen:** Özel paywallınız Adapty'den çekilen ürünleri gösterir. Bir ürüne dokunmak sandbox satın alma diyalogunu tetikler. - **Dikkat:** Boş ürünler dizisi → paywalla kontrol panelinde ürün atandığını ve placement'ın bir kitleye sahip olduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Gözlemci modu"> **Rehberler:** - [Gözlemci moduna genel bakış](observer-vs-full-mode) - [Gözlemci modunu uygulayın](implement-observer-mode-kmp) - [Gözlemci modunda işlemleri bildirin](report-transactions-observer-mode-kmp) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-kmp.md - https://adapty.io/docs/tr/report-transactions-observer-mode-kmp.md ``` :::tip[Kontrol noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak sandbox'ta satın alma yaptıktan sonra işlem Adapty kontrol panelinin **Event Feed** bölümünde görünür. - **Dikkat:** Hiç olay yok → işlemleri Adapty'ye bildirdiğinizi ve her iki mağaza için sunucu bildirimlerinin yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol edin \{#check-subscription-status\} Satın alma sonrasında premium içeriği kısıtlamak için kullanıcı profilinde aktif bir access level kontrol edin. **Rehber:** [Abonelik durumunu kontrol et](kmp-check-subscription-status) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/kmp-check-subscription-status.md ``` :::tip[Kontrol noktası] - **Beklenen:** Sandbox satın almasının ardından `profile.accessLevels["premium"]?.isActive` `true` döndürür. - **Dikkat:** Satın alma sonrası `accessLevels` boş → ürünün kontrol panelinde bir access level atandığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Satın almaların cihazlar arasında kalıcı olması için uygulama kullanıcı hesaplarınızı Adapty profillerine bağlayın. :::important Uygulamanızın kimlik doğrulaması yoksa bu adımı atlayın. ::: **Rehber:** [Kullanıcıları tanımla](kmp-quickstart-identify) LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/kmp-quickstart-identify.md ``` :::tip[Kontrol noktası] - **Beklenen:** `Adapty.identify("your-user-id")` çağrıldıktan sonra kontrol panelinin **Profiles** bölümü özel kullanıcı ID'nizi gösterir. - **Dikkat:** Anonim profil attribution'ını önlemek için `identify`'ı etkinleştirmeden sonra ancak paywall çekmeden önce çağırın. ::: ### Yayına hazırlanın \{#prepare-for-release\} Entegrasyon sandbox'ta çalışır hale gelince, her şeyin üretime hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Rehber:** [Yayın kontrol listesi](release-checklist) LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Kontrol noktası] - **Beklenen:** Tüm kontrol listesi maddeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Eksik sunucu bildirimleri → **App settings → iOS SDK** bölümünde App Store Server Notifications'ı ve **App settings → Android SDK** bölümünde Google Play Real-Time Developer Notifications'ı yapılandırın. ::: ## Düz metin doküman dizin dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty dokümantasyonunu listeleyen veya birleştiren dizin dosyaları sunuyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı yapay zeka ajanlarında (ör. ChatGPT) `llms.txt`'i indirip sohbete dosya olarak yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hali. Çok büyük — yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Kotlin Multiplatform'a özel [`kmp-llms.txt`](https://adapty.io/docs/tr/kmp-llms.txt) ve [`kmp-llms-full.txt`](https://adapty.io/docs/tr/kmp-llms-full.txt): Tam siteye kıyasla daha az token harcayan platforma özel alt kümeler. --- # File: kmp-paywalls --- --- title: "Flow'lar ve paywalllar - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda Adapty Flow Builder veya Paywall Builder ile oluşturulmuş flow'ları ve paywallları görüntüleyin ve yönetin." --- ## Paywallları görüntüleme \{#display-paywalls\} ### Adapty Flow Builder & Paywall Builder \{#adapty-flow-builder--paywall-builder\} <CustomDocCardList ids={['kmp-get-pb-paywalls', 'kmp-present-paywalls', 'kmp-handling-events', 'kmp-handle-paywall-actions']} /> :::tip Adapty Paywall Builder paywalllarına hızlıca başlamak için [hızlı başlangıç kılavuzumuza](kmp-quickstart-paywalls) göz atın. ::: ### Paywallları manuel olarak uygulama \{#implement-paywalls-manually\} <CustomDocCardList ids={['kmp-quickstart-manual', 'fetch-paywalls-and-products-kmp', 'present-remote-config-paywalls-kmp', 'kmp-making-purchases']} /> Paywallları manuel olarak uygulama ve satın almaları yönetme hakkında daha fazla kılavuz için [kategoriye](kmp-implement-paywalls-manually) bakın. ## Faydalı özellikler \{#useful-features\} <CustomDocCardList ids={['kmp-use-fallback-paywalls', 'kmp-web-paywalls']} /> --- # File: kmp-get-pb-paywalls --- --- title: "Flow ve paywall alma - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda Adapty'den flow ve paywall'ları getirin." --- <SDKv4> <MethodPromo method="getFlow" /> [Flow veya Paywall Builder paywallınızı tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda görüntüleyebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywallı ve bunların görünüm yapılandırmasını almaktır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-kotlin-multiplatform) kurun. </details> ## Flow/paywall getirme \{#fetch-flowpaywall\} Flow Builder veya Paywall Builder ile bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir flow veya paywall, içinde neyin ve nasıl gösterileceğini zaten barındırır. Yine de placement aracılığıyla ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, flow veya paywall'ı ve bunların [görünüm yapılandırmasını](kmp-get-pb-paywalls#fetch-the-view-configuration) mümkün olduğunca erken almanız kritik öneme sahiptir; böylece görseller kullanıcıya sunulmadan önce indirmek için yeterli süre tanınmış olur. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```kotlin showLineNumbers Adapty.getFlow( placementId = "YOUR_PLACEMENT_ID", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { flow -> // istenen flow/paywall }.onError { error -> // hatayı işle } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, oturum sırasında gereksiz ağ isteklerini önlemek amacıyla kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, flow'ları ve paywall'ları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Ayrıca daha hızlı yükleme için CDN, CDN'e ulaşılamadığında ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en son sürümü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p>İşlemin arka planda farklı isteklerden oluşabileceği göz önünde bulundurulduğunda, nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.</p><p>Kotlin Multiplatform için: `Duration` nesnesini `5.seconds` gibi uzantı fonksiyonlarıyla oluşturabilirsiniz; burada `.seconds`, `kotlin.time.Duration.Companion.seconds` kaynağından gelir.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :---------- | | Flow | Placement'ı, tanımlayıcıları (`instanceIdentity`, `variationId`), adı, paywall varyasyonlarını (`paywalls` — `AdaptyFlowPaywall` listesi) ve remote config'leri (`remoteConfigs` — her locale için bir girdi içeren liste) barındıran `AdaptyFlow` nesnesi. Ön yükleme, özel arayüz veya programatik kontroller için gerçek ürünleri getirmek istiyorsanız `getPaywallProducts(flow)` metodunu çağırın. | ## View yapılandırmasını getir \{#fetch-the-view-configuration\} Flow veya paywall'ı getirdikten sonra, `createFlowView` metoduyla view yapılandırmasını yükleyin ve view'ı tek adımda oluşturun. Kontrol etmeniz gereken ayrı bir bayrak yoktur: placement **Flow Builder**'da (flow) veya **Paywall Builder**'da (paywall) tasarlanmışsa, `createFlowView` sunuma hazır view'ı döndürür. Placement, Builder arayüzü olmayan özel bir paywall ise `createFlowView` bir `AdaptyResult.Error` döndürür — [bunu remote config paywall olarak ele alın](present-remote-config-paywalls-kmp). :::important Flow Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm yapılandırması alınamaz. ::: ```kotlin showLineNumbers AdaptyUI.createFlowView( flow = flow, loadTimeout = 5.seconds, preloadProducts = true ).onSuccess { view -> // use view }.onError { error -> // the flow has no view configured, or view creation failed } ``` | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :------------- | :----------------------------------------------------------- | | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | | **loadTimeout** | isteğe bağlı | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa, önbelleğe alınmış veriler veya yerel yedek döndürülür. Nadir durumlarda bu metod, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir; çünkü işlem arka planda farklı isteklerden oluşabilir. `kotlin.time.Duration.Companion` paketinden `5.seconds` gibi uzantı fonksiyonlarını kullanabilirsiniz. | | **preloadProducts** | isteğe bağlı | Daha iyi performans için ürünleri önceden yüklemek üzere `true` olarak ayarlayın. Etkinleştirildiğinde, ürünler önceden yüklenerek flow veya paywall'ın görüntülenmesi için gereken süre azaltılır. | | **productPurchaseParameters** | isteğe bağlı | [`AdaptyProductIdentifier`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-product-identifier/) ile [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) arasındaki bir eşleme. Flow veya paywall'daki bireysel ürünler için kişiselleştirilmiş teklifler veya abonelik güncelleme parametreleri gibi satın alma'ya özgü parametreleri yapılandırmak için kullanın. | :::note Birden fazla dil kullanıyorsanız, [Builder yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi öğrenin. ::: Yüklendikten sonra [flow veya paywall'ı gösterin](kmp-present-paywalls). ## Varsayılan kitle için flow veya paywall alarak daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında yüklenir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall'ı yüklemek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bunu gidermek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ını çeken `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu anlamak kritik önem taşır: önerilen yaklaşım, flow veya paywall'ı yukarıdaki [Flow/paywall'ı getir](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklandığı şekilde `getFlow` metoduyla çekmektir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Potansiyel geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecekteki) farklı flow'lar göstermeniz gerekirse zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesine yönelik tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre hedefleme dahil) kaybettiğiniz anlamına gelir. Bu dezavantajları göze alarak daha hızlı flow veya paywall getirme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-flowpaywall) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { flow -> // the requested flow }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK, varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği kullanmanızı öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri mevcutsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; dolayısıyla oturum sırasında ağ isteklerinden kaçınmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin, uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde ya da manuel temizlik yapıldığında temizlendiğini unutmayın.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Flow veya paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterme. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterme. - Video başlamadan önce bir önizleme görseli gösterme. İşte özel varlıkları bir map aracılığıyla nasıl sağlayabileceğinize dair bir örnek: :::info Kotlin Multiplatform SDK yalnızca yerel varlıkları destekler. Uzak içerikler için, bunları özel varlıklarda kullanmadan önce indirip yerel olarak önbelleğe almanız gerekir. ::: ```kotlin showLineNumbers // Import generated Res class for accessing resources viewModelScope.launch { // Get URIs for bundled resources using Res.getUri() val heroImagePath = Res.getUri("files/images/hero_image.png") val demoVideoPath = Res.getUri("files/videos/demo_video.mp4") // Or read image as byte data val imageByteData = Res.readBytes("files/images/avatar.png") // Create custom assets map val customAssets: Map<String, AdaptyCustomAsset> = mapOf( // Load image from app resources (bundled with the app) // Files should be placed in commonMain/composeResources/files/ "hero_image" to AdaptyCustomAsset.localImageResource( path = heroImagePath ), // Or use image byte data "avatar" to AdaptyCustomAsset.localImageData( data = imageByteData ), // Load video from app resources "demo_video" to AdaptyCustomAsset.localVideoResource( path = demoVideoPath ), // Or use a video file from device storage "intro_video" to AdaptyCustomAsset.localVideoFile( path = "/path/to/local/video.mp4" ), // Apply custom brand colors "brand_primary" to AdaptyCustomAsset.color( colorHex = "#FF6B35" ), // Create gradient background "card_gradient" to AdaptyCustomAsset.linearGradient( colors = listOf("#1E3A8A", "#3B82F6", "#60A5FA"), stops = listOf(0.0f, 0.5f, 1.0f) ) ) // Use custom assets when creating the flow view AdaptyUI.createFlowView( flow = flow, customAssets = customAssets ).onSuccess { view -> // Present the flow with custom assets view.present() }.onError { error -> // Handle the error - the flow will fall back to default appearance } } ``` :::note Bir varlık bulunamazsa veya yüklenemezse, flow veya paywall Builder'da yapılandırılan varsayılan görünümüne geri döner. ::: </SDKv4> <SDKv3> Adapty Kontrol Paneli'ndeki yeni Paywall Builder ile [paywall'unuzun görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywall'u ve görünüm yapılandırmasını almaktır. Paywall Builder ile özelleştirilmiş paywalllar için bu konuya başvurduğunuzu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywalllar için paywallları ve ürünleri getirme](fetch-paywalls-and-products-kmp) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywallları göstermeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-kotlin-multiplatform) yükleyin. </details> ## Paywall Builder ile tasarlanan paywall'ı getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder ile bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir paywall; paywall içinde ne gösterileceğini ve bunların nasıl gösterileceğini zaten içerir. Yine de placement üzerinden paywall ID'sini, görünüm yapılandırmasını almanız ve ardından bunu mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, görsellerin kullanıcıya sunulmadan önce indirilmesine yeterli zaman tanımak amacıyla paywall'ı ve [görünüm yapılandırmasını](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız kritik önem taşır. Paywall almak için `getPaywall` metodunu kullanın: ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve önerilen kullanım biçimleri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, mevcut önbellek verisini döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en son verileri göremeyebilir; ancak bağlantı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşar. Önbellek düzenli olarak güncellenir, dolayısıyla oturum boyunca ağ isteklerinden kaçınmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında korunduğunu; yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e erişilemediğinde ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısı yetersiz olduğunda dahi her zaman paywalllarınızın en güncel sürümüne erişeceğinizi garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbellekteki veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun zaman aşımı, `loadTimeout` içinde belirtilenden biraz daha geç gerçekleşebilir; çünkü işlem arka planda farklı isteklerden oluşabilir.</p><p>Kotlin Multiplatform için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`; burada `.seconds`, `import com.adapty.utils.seconds`'tan gelir) ya da `TimeInterval.seconds(5)` kullanabilirsiniz. Sınır koymamak için `TimeInterval.INFINITE` kullanın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) nesnesi. | ## Paywall Builder ile tasarlanan paywallın görünüm yapılandırmasını getirme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse görünüm yapılandırması alınamaz. ::: Paywall'ı aldıktan sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren `ViewConfiguration` öğesini içerip içermediğini kontrol edin. Bu, paywall'ı nasıl göstereceğiniz konusunda size rehberlik eder. `ViewConfiguration` mevcutsa Paywall Builder paywall'ı olarak değerlendirin; yoksa [remote config paywall olarak ele alın](present-remote-config-paywalls-kmp). Görünüm yapılandırmasını yüklemek için `createPaywallView` metodunu kullanın. ```kotlin showLineNumbers if (paywall.hasViewConfiguration) { AdaptyUI.createPaywallView( paywall = paywall, loadTimeout = 5.seconds, preloadProducts = true ).onSuccess { paywallView -> // use paywallView }.onError { error -> // handle the error } } else { // use your custom logic } ``` | Parametre | Zorunluluk | Açıklama | | :--------------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir controller almak üzere kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | isteğe bağlı | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbellekteki veri veya yerel yedek döndürülür. Nadir durumlarda bu metodun zaman aşımı, `loadTimeout` içinde belirtilenden biraz daha geç gerçekleşebilir; çünkü işlem arka planda farklı isteklerden oluşabilir. `kotlin.time.Duration.Companion` kaynaklı `5.seconds` gibi uzantı fonksiyonlarını kullanabilirsiniz. | | **preloadProducts** | isteğe bağlı | Daha iyi performans için ürünleri önceden yüklemek üzere `true` olarak ayarlayın. Etkinleştirildiğinde ürünler önceden yüklenir ve paywall'ın gösterilmesi için gereken süre azalır. | | **productPurchaseParams** | isteğe bağlı | [`AdaptyProductIdentifier`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-product-identifier/) ile [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) arasındaki bir eşleme. Paywalldaki her bir ürün için kişiselleştirilmiş teklifler veya abonelik güncelleme parametreleri gibi satın alma'ya özgü parametreleri yapılandırmak için kullanın. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) nasıl ekleneceğini öğrenin. ::: Yüklendikten sonra [paywall'ı sunun](kmp-present-paywalls). ## Daha hızlı getirmek için varsayılan kitle paywallını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Paywalllar genellikle neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywalla sahip olduğunuzda ve kullanıcılarınızın internet bağlantısı zayıf olduğunda, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir paywall görüntülemek isteyebilirsiniz. Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesine ait paywallını getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Getirme](#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklanan `getPaywall` metodu olduğunu unutmayın. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun bazı önemli dezavantajları vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalacaksınız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywalllarla karşılaşmasını kabul edeceksiniz. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize göre) ortadan kaldırır. Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve önerilen kullanım biçimleri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, mevcut önbellek verisini döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en son verileri göremeyebilir; ancak bağlantı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşar. Önbellek düzenli olarak güncellenir, dolayısıyla oturum boyunca ağ isteklerinden kaçınmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında korunduğunu; yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Paywallinızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Kahraman görselleri ve videoları önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde bu öğeleri ID'leri aracılığıyla hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterin. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterin. - Video çalışmadan önce bir önizleme görseli gösterin. :::important Bu özelliği kullanmak için Adapty SDK'yı 3.7.0 veya üzeri sürüme güncelleyin. ::: Özel varlıkları bir map aracılığıyla nasıl sağlayabileceğinize dair bir örnek: :::info Kotlin Multiplatform SDK yalnızca yerel varlıkları destekler. Uzak içerikler için, özel varlıklarda kullanmadan önce varlıkları indirip yerel olarak önbelleğe almanız gerekir. ::: ```kotlin showLineNumbers // Import generated Res class for accessing resources viewModelScope.launch { // Get URIs for bundled resources using Res.getUri() val heroImagePath = Res.getUri("files/images/hero_image.png") val demoVideoPath = Res.getUri("files/videos/demo_video.mp4") // Or read image as byte data val imageByteData = Res.readBytes("files/images/avatar.png") // Create custom assets map val customAssets: Map<String, AdaptyCustomAsset> = mapOf( // Load image from app resources (bundled with the app) // Files should be placed in commonMain/composeResources/files/ "hero_image" to AdaptyCustomAsset.localImageResource( path = heroImagePath ), // Or use image byte data "avatar" to AdaptyCustomAsset.localImageData( data = imageByteData ), // Load video from app resources "demo_video" to AdaptyCustomAsset.localVideoResource( path = demoVideoPath ), // Or use a video file from device storage "intro_video" to AdaptyCustomAsset.localVideoFile( path = "/path/to/local/video.mp4" ), // Apply custom brand colors "brand_primary" to AdaptyCustomAsset.color( colorHex = "#FF6B35" ), // Create gradient background "card_gradient" to AdaptyCustomAsset.linearGradient( colors = listOf("#1E3A8A", "#3B82F6", "#60A5FA"), stops = listOf(0.0f, 0.5f, 1.0f) ) ) // Use custom assets when creating paywall view AdaptyUI.createPaywallView( paywall = paywall, customAssets = customAssets ).onSuccess { paywallView -> // Present the paywall with custom assets paywallView.present() }.onError { error -> // Handle the error - paywall will fall back to default appearance } } ``` :::note Bir asset bulunamaz veya yüklenemezse, paywall Paywall Builder'da yapılandırılmış varsayılan görünümüne geri döner. ::: </SDKv3> --- # File: kmp-present-paywalls --- --- title: "Flow ve paywallları gösterme - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda kullanıcılara flow ve paywallları sunun." --- <SDKv4> <MethodPromo method="getFlow" label="Flow ve paywallları göster" /> Bir flow veya paywall oluşturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etme konusunda endişelenmenize gerek yoktur. Böyle bir flow veya paywall, içinde neyin gösterileceğini ve nasıl gösterileceğini zaten kapsar. :::warning Bu kılavuz, Adapty tarafından render edilen flow'ları ve **yeni Paywall Builder paywall'larını** kapsar. Remote config paywall'ları ve [Observer mode](observer-vs-full-mode) için süreç farklıdır. - **Remote config paywalls** sunmak için, bkz. [Remote config ile tasarlanmış paywall'ı render etme](present-remote-config-paywalls-kmp). - **Observer mode**'da flow'ları sunmak için, bkz. [Observer mode'da flow'ları sunma](kmp-present-flows-in-observer-mode). ::: Aşağıda kullanılan `flow` nesnesini edinmek için bkz. [Flow'ları ve paywall'ları alma](kmp-get-pb-paywalls). Adapty Kotlin Multiplatform SDK, flow'ları ve paywall'ları sunmak için iki yöntem sunar: - **Compose Multiplatform ile** - **Compose Multiplatform olmadan** ## Compose Multiplatform ile \{#with-compose-multiplatform\} Bir flow veya paywall görüntülemek için [`createFlowView`](kmp-get-pb-paywalls#fetch-the-view-configuration) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Flow'u tekrar görüntülemeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createFlowView` metodunu bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak hataya yol açabilir. ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createFlowView(flow = flow).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### İletişim Kutusu Göster \{#show-dialog\} Flow veya paywall, Android'de gösterildiğinde yerel uyarı iletişim kutuları yerine bu yöntemi kullanın. Android'de normal uyarılar, flow görünümünün arkasında kalır ve kullanıcılar tarafından görülmez. Bu yöntem, tüm platformlarda flow'un üzerinde iletişim kutusunun düzgün şekilde gösterilmesini sağlar. ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { view.showDialog( title = "Close this screen?", content = "You will lose access to exclusive offers.", primaryActionTitle = "Stay", secondaryActionTitle = "Close" ).onSuccess { action -> if (action == AdaptyUIDialogActionType.SECONDARY) { // User confirmed - close the flow view.dismiss() } // If primary - do nothing, user stays }.onError { error -> // handle the error } } ``` ### iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} Flow veya paywall'ın iOS'ta nasıl sunulacağını yapılandırmak için `present()` metoduna `iosPresentationStyle` parametresini geçirin. Bu parametre `AdaptyUIIOSPresentationStyle.FULLSCREEN` (varsayılan) veya `AdaptyUIIOSPresentationStyle.PAGESHEET` değerlerini kabul eder. ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createFlowView(flow = flow).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ## Compose Multiplatform Olmadan \{#without-compose-multiplatform\} :::note `createNativeFlowView`, `io.adapty:adapty-kmp` çekirdek modülünün bir parçasıdır. Projeniz Compose Multiplatform kullanmıyorsa `io.adapty:adapty-kmp-ui` bağımlılığına ihtiyacınız yoktur. ::: Compose Multiplatform olmadan bir flow veya paywall yerleştirmek için `createNativeFlowView` metodunu çağırın. Bu metot, layout'unuza eklediğiniz bir `AdaptyNativeFlowView` döndürür: <Tabs> <TabItem value="android" label="Android"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativeFlowView( context = context, viewModelStoreOwner = activity, flow = flow, observer = myFlowObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` Varsayılan olarak, gömülü bir view güvenli alan dolguları uygulamaz — layout'unuzun iç boşlukları kendisinin yönetmesi beklenir. View'ın bu dolguları kendisi uygulamasını istiyorsanız, `createNativeFlowView` fonksiyonuna `androidEnableSafeArea = true` parametresini geçin. Bu parametre yalnızca Android'e özgüdür. </TabItem> <TabItem value="ios" label="iOS"> KMP arayüz varsayılan metotları Swift'te `@required` olarak çevrildiğinden, `AdaptyUIFlowsEventsObserver`'ı doğrudan Swift üzerinden uygulayamazsınız. Önce `iosMain` içinde açık bir temel sınıf tanımlayın: ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BaseFlowObserver : AdaptyUIFlowsEventsObserver ``` Ardından Swift'te yalnızca ihtiyacınız olanı geçersiz kılarak alt sınıf oluşturun: ```swift showLineNumbers title="Swift" class MyFlowObserver: BaseFlowObserver { override func flowViewDidPerformAction(view: AdaptyUIFlowView, action: any AdaptyUIAction) { if action is AdaptyUIActionCloseAction { // remove nativeView from your view hierarchy } } } let nativeView = AdaptyUI.shared.createNativeFlowView( flow: flow, observer: MyFlowObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` </TabItem> </Tabs> ### Görünümü imha etme \{#dispose-the-view\} Görünümü düzeninizden kaldırırken `dispose()` metodunu çağırın. Bu işlem, olay dinleyicisinin kaydını siler ve dahili kaynakları serbest bırakır. ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` ## Özel etiketler Özel etiketler, farklı senaryolar için ayrı flow'lar veya paywall'lar oluşturmaktan kurtarır. Kullanıcı verilerine göre dinamik olarak uyum sağlayan tek bir flow hayal edin. Örneğin, genel bir "Merhaba!" yerine kullanıcıları "Merhaba, Ahmet!" veya "Merhaba, Ayşe!" şeklinde kişisel olarak selamlayabilirsiniz. Özel etiketleri şu şekillerde kullanabilirsiniz: - Flow veya paywall'da kullanıcının adını ya da e-posta adresini gösterin. - Satışları artırmak için haftanın günü bilgisini gösterin (örneğin, "İyi Perşembeler"). - Sattığınız ürünlerle ilgili kişiselleştirilmiş ayrıntılar ekleyin (bir fitness programının adı veya VoIP uygulamasında bir telefon numarası gibi). Özel etiketler, çeşitli durumlara uyum sağlayan esnek bir flow oluşturmanıza yardımcı olarak uygulamanızın arayüzünü daha kişisel ve ilgi çekici hale getirir. :::warning Bazı durumlarda uygulamanız, özellikle kullanıcılar eski bir AdaptyUI SDK sürümü kullanıyorsa, özel etiketi neyle değiştireceğini bilemeyebilir. Bunu önlemek için, bilinmeyen özel etiket içeren satırların yerine geçecek her zaman bir yedek metin ekleyin. Aksi takdirde kullanıcılar etiketleri kod olarak görebilir (`<USERNAME/>`). ::: Özel etiketleri flow'unuzda veya paywallınızda kullanmak için, flow view oluştururken bunları iletmeniz gerekir: <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) AdaptyUI.createFlowView( flow = flow, customTags = customTags ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativeFlowView( context = context, viewModelStoreOwner = activity, flow = flow, observer = myFlowObserver, customTags = customTags, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativeFlowView( flow = flow, observer = myFlowObserver, customTags = customTags, ) ``` </TabItem> </Tabs> ## Özel zamanlayıcılar \{#custom-timers\} Zamanlayıcı, süreli özel ve sezonluk teklifleri tanıtmak için harika bir araçtır. Ancak bu zamanlayıcının teklifin geçerlilik süresiyle veya kampanyanın bitiş tarihiyle herhangi bir bağlantısı olmadığını belirtmek gerekir. Yalnızca belirlediğiniz değerden başlayıp sıfıra kadar azalan bağımsız bir geri sayımdır. Zamanlayıcı sıfıra ulaştığında hiçbir şey olmaz; sadece sıfırda kalır. İstediğiniz mesajı oluşturmak için zamanlayıcının önüne ve arkasına metin ekleyebilirsiniz; örneğin: "Teklif bitiyor: 10:00 sn." Flow veya paywallınızda özel zamanlayıcılar kullanmak için, flow görünümünü oluştururken bunları aktarın: <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) AdaptyUI.createFlowView( flow = flow, customTimers = customTimers ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativeFlowView( context = context, viewModelStoreOwner = activity, flow = flow, observer = myFlowObserver, customTimers = customTimers, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativeFlowView( flow = flow, observer = myFlowObserver, customTimers = customTimers, ) ``` </TabItem> </Tabs> </SDKv4> <SDKv3> Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz yalnızca **yeni Paywall Builder paywallları** içindir. Paywall sunma süreci, remote config paywallları ve [Observer mode](observer-vs-full-mode) ile tasarlanan paywalllar için farklıdır. **Remote config paywalllarını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls-kmp). ::: Adapty Kotlin Multiplatform SDK, paywall'ları sunmak için iki yöntem sunar: - **Compose Multiplatform ile** - **Compose Multiplatform olmadan** ## Compose Multiplatform ile \{#with-compose-multiplatform\} Bir paywall görüntülemek için, [`createPaywallView`](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metodu tarafından oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar görüntülemeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `createPaywallView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak hataya yol açabilir. ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createPaywallView(paywall = paywall).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### Diyalog Göster \{#show-dialog\} Android'de bir paywall görünümü sunulurken yerel uyarı diyalogları yerine bu yöntemi kullanın. Android'de normal uyarılar, paywall görünümünün arkasında görünür; bu da onları kullanıcılar için görünmez hale getirir. Bu yöntem, tüm platformlarda paywall'ın üzerinde diyaloğun düzgün şekilde gösterilmesini sağlar. ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { view.showDialog( title = "Close paywall?", content = "You will lose access to exclusive offers.", primaryActionTitle = "Stay", secondaryActionTitle = "Close" ).onSuccess { action -> if (action == AdaptyUIDialogActionType.SECONDARY) { // User confirmed - close the paywall view.dismiss() } // If primary - do nothing, user stays }.onError { error -> // handle the error } } ``` ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek paywallın iOS'ta nasıl sunulacağını yapılandırın. Parametre, `AdaptyUIIOSPresentationStyle.FULLSCREEN` (varsayılan) veya `AdaptyUIIOSPresentationStyle.PAGESHEET` değerlerini kabul eder. ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createPaywallView(paywall = paywall).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ## Compose Multiplatform Olmadan \{#without-compose-multiplatform\} :::note `createNativePaywallView`, `io.adapty:adapty-kmp` çekirdek modülünün bir parçasıdır. Projeniz Compose Multiplatform kullanmıyorsa `io.adapty:adapty-kmp-ui` bağımlılığına ihtiyacınız yoktur. ::: Compose Multiplatform olmadan bir paywall gömmek için `createNativePaywallView` fonksiyonunu çağırın. Bu fonksiyon, layout'unuza eklediğiniz bir `AdaptyNativePaywallView` döndürür: <Tabs> <TabItem value="android" label="Android"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` </TabItem> <TabItem value="ios" label="iOS"> KMP arayüzü varsayılan metodları Swift'te `@required` hale geldiğinden, `AdaptyUIPaywallsEventsObserver`'ı doğrudan Swift'ten implemente edemezsiniz. Önce `iosMain` içinde açık bir temel sınıf tanımlayın: ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BasePaywallObserver : AdaptyUIPaywallsEventsObserver ``` Ardından Swift'te bu sınıfı alt sınıf olarak genişletin ve yalnızca ihtiyacınız olanları geçersiz kılın: ```swift showLineNumbers title="Swift" class MyPaywallObserver: BasePaywallObserver { override func paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: any AdaptyUIAction) { if action is AdaptyUIActionCloseAction { // remove nativeView from your view hierarchy } } } let nativeView = AdaptyUI.shared.createNativePaywallView( paywall: paywall, observer: MyPaywallObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` </TabItem> </Tabs> ### Görünümü serbest bırakın \{#dispose-the-view\} Görünümü düzeninizden kaldırırken `dispose()` metodunu çağırın. Bu işlem, olay dinleyicisinin kaydını siler ve dahili kaynakları serbest bırakır. ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` ## Özel etiketler \{#custom-tags\} Özel etiketler, farklı senaryolar için ayrı ayrı paywall oluşturma zahmetini ortadan kaldırır. Tek bir paywall'un kullanıcı verilerine göre dinamik biçimde uyarlandığını hayal edin. Örneğin genel bir "Merhaba!" yerine kullanıcıları "Merhaba, Ahmet!" ya da "Merhaba, Ayşe!" şeklinde kişisel olarak selamlayabilirsiniz. Özel etiketleri şu amaçlarla kullanabilirsiniz: - Paywall üzerinde kullanıcının adını veya e-posta adresini göstermek. - Satışları artırmak için haftanın gününü göstermek (ör. "İyi Perşembeler"). - Sattığınız ürünlere ilişkin kişiselleştirilmiş ayrıntılar eklemek (bir fitness programının adı veya VoIP uygulamasında bir telefon numarası gibi). Özel etiketler, çeşitli durumlara uyum sağlayan esnek bir paywall oluşturmanıza yardımcı olarak uygulamanızın arayüzünü daha kişisel ve ilgi çekici hale getirir. :::warning Bazı durumlarda, uygulamanız bir özel etiketi neyle değiştireceğini bilemeyebilir; özellikle kullanıcılar AdaptyUI SDK'nın eski bir sürümünü kullanıyorsa. Bunu önlemek için, bilinmeyen özel etiketler içeren satırların yerine geçecek bir yedek metin eklemeyi unutmayın. Aksi takdirde kullanıcılar etiketleri kod olarak görebilir (`<USERNAME/>`). ::: Paywall'ınızda özel etiketleri kullanmak için, paywall görünümünü oluştururken bunları iletin: <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) AdaptyUI.createPaywallView( paywall = paywall, customTags = customTags ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` </TabItem> </Tabs> ## Özel zamanlayıcılar \{#custom-timers\} Paywall zamanlayıcısı, süreli özel ve sezonluk teklifleri tanıtmak için harika bir araçtır. Ancak bu zamanlayıcının teklifin geçerlilik süresiyle veya kampanyanın uzunluğuyla herhangi bir bağlantısı olmadığını belirtmek gerekir. Belirlediğiniz değerden başlayıp sıfıra kadar geri sayan bağımsız bir geri sayım saatidir. Zamanlayıcı sıfıra ulaştığında hiçbir şey olmaz; sadece sıfırda kalır. İstediğiniz mesajı oluşturmak için zamanlayıcının önüne ve arkasına metin ekleyebilirsiniz; örneğin: "Teklif bitiyor: 10:00 sn." Paywall'unuzda özel zamanlayıcılar kullanmak için, paywall view'ını oluştururken bunları aktarın: <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) AdaptyUI.createPaywallView( paywall = paywall, customTimers = customTimers ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` </TabItem> </Tabs> </SDKv3> --- # File: kmp-handle-paywall-actions --- --- title: "Flow aksiyonlarına yanıt verme - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda flow ve paywall'lardan gelen buton aksiyonlarını yönetin." --- <SDKv4> Adapty Flow Builder veya Paywall Builder kullanarak flow veya paywall oluşturuyorsanız butonları doğru şekilde ayarlamak kritik öneme sahiptir: 1. [Builder'da bir buton ekleyin](paywall-buttons) ve bu butona önceden tanımlanmış bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, özel ve önceden tanımlanmış eylemleri kodunuzda nasıl ele alacağınızı gösterir. :::warning **Yalnızca satın almalar, geri yüklemeler, flow/paywall kapatmaları ve bağlantı açmaları otomatik olarak işlenir.** Özel eylemler gibi diğer tüm buton eylemleri, uygulama kodunda doğru şekilde ele alınmasını gerektirir. ::: ## AdaptyUIFlowsEventsObserver'ı Kurma \{#set-up-the-adaptyuiflowseventssobserver\} Flow eylemlerini yönetmek için `AdaptyUIFlowsEventsObserver` arayüzünü uygulamanız ve `AdaptyUI.setFlowsEventsObserver()` ile kurmanız gerekir. Bu işlem, uygulamanızın yaşam döngüsünün erken aşamasında, genellikle ana aktivitede veya uygulama başlatma sürecinde yapılmalıdır. ```kotlin // In your app initialization AdaptyUI.setFlowsEventsObserver(MyAdaptyUIFlowsEventsObserver()) ``` Tüm buton aksiyonları, `flowViewDidPerformAction(view, action)` callback'ine `AdaptyUIAction` sealed class olarak gelir: `CloseAction`, `AndroidSystemBackAction`, `OpenUrlAction` veya `CustomAction`. :::warning `flowViewDidPerformAction` override edildiğinde, yalnızca ilgilendiğiniz aksiyonun değil, **tüm** aksiyonların varsayılan davranışı değişir. Aşağıdaki örneklerde gösterildiği gibi, `CloseAction` (flow'u kapat) ve `OpenUrlAction` (URL'i aç) için varsayılan dalları değiştirmeyi amaçlamıyorsanız bunları koruyun. ::: ## Flow ve paywall'ları kapatma \{#close-flows-and-paywalls\} Flow veya paywall'ınıza kapatma düğmesi eklemek için: 1. Builder'da bir düğme ekleyin ve **Close** aksiyonunu atayın. 2. Uygulama kodunuzda, flow'u kapatan `close` aksiyonu için bir handler uygulayın. :::info Kotlin Multiplatform SDK'sında `CloseAction`, varsayılan olarak flow veya paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir flow'un kapatılması başka bir flow'un açılmasını tetikleyebilir. ::: ```kotlin class MyAdaptyUIFlowsEventsObserver : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> mainUiScope.launch { view.dismiss() } // default behavior is AdaptyUIAction.OpenUrlAction -> AdaptyUI.openWebUrl(action.url, action.openIn) // default behavior else -> Unit } } } // Set up the observer AdaptyUI.setFlowsEventsObserver(MyAdaptyUIFlowsEventsObserver()) ``` [`createNativeFlowView`](kmp-present-paywalls#without-compose-multiplatform) kullanıyorsanız, `view.dismiss()` çağrısının hiçbir etkisi yoktur — görünüm KMP yığını üzerinden sunulmaz, doğrudan layout'unuza gömülür. Bunun yerine görünümü layout'unuzdan kaldırın ve üzerinde `dispose()` çağırın. ## Android sistem geri tuşunu yönetme \{#handle-the-android-system-back-button\} Android sistem geri tuşuna basmak (veya geri hareketini kullanmak) `AdaptyUIAction.AndroidSystemBackAction` olayını tetikler. Varsayılan olarak bu eylem yok sayılır — flow açık kalır ve kullanıcı, builder'da tanımladığınız **Close** butonu veya `on_device_back` eylemi gibi bir yoldan çıkış yapar. Sistem geri tuşunun flow'u kapatmasını istiyorsanız, eylemi kendiniz ele alın: ```kotlin class MyAdaptyUIFlowsEventsObserver : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> mainUiScope.launch { view.dismiss() } // default behavior is AdaptyUIAction.AndroidSystemBackAction -> mainUiScope.launch { view.dismiss() } // not handled by default is AdaptyUIAction.OpenUrlAction -> AdaptyUI.openWebUrl(action.url, action.openIn) // default behavior else -> Unit } } } ``` ## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde ele alın. ::: Flow veya paywall'ınıza bir bağlantı açan düğme eklemek için (örneğin, **Terms of use** veya **Privacy policy**), builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. Varsayılan olarak, SDK alınan URL'yi yerel olarak açar — `action.openIn` değerine bağlı olarak harici veya uygulama içi tarayıcıda — bu nedenle herhangi bir kod gerekmez. Yalnızca önce bir onay iletişim kutusu göstermek gibi özel bir mantık istiyorsanız işleyiciyi geçersiz kılın: ```kotlin class MyAdaptyUIFlowsEventsObserver( private val uriHandler: UriHandler ) : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.OpenUrlAction -> { // Show confirmation dialog before opening URL mainUiScope.launch { val selectedAction = view.showDialog( title = "Open URL?", content = action.url, primaryActionTitle = "Cancel", secondaryActionTitle = "Open" ).getOrNull() when (selectedAction) { AdaptyUIDialogActionType.PRIMARY -> { // User cancelled } AdaptyUIDialogActionType.SECONDARY -> { // User confirmed - open URL uriHandler.openUri(action.url) } else -> Unit } } } else -> Unit } } } // Set up the observer with UriHandler AdaptyUI.setFlowsEventsObserver(MyAdaptyUIFlowsEventsObserver(uriHandler)) ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir buton eklemek için: 1. Builder'da bir buton ekleyin ve bu butona "login" ID'sine sahip bir **Custom** (Özel) eylem atayın. 2. Uygulama kodunuzda, kullanıcıyı tanımlayan özel eylem için bir işleyici (handler) uygulayın. ```kotlin class MyAdaptyUIFlowsEventsObserver : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { if (action.action == "login") { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } else -> Unit } } } ``` ## Özel eylemleri işleme \{#handle-custom-actions\} Herhangi bir eylemi işleyen bir buton eklemek için: 1. Builder'da bir buton ekleyin, **Custom** eylemini atayın ve bir kimlik (ID) verin. 2. Uygulama kodunuzda, oluşturduğunuz eylem kimliği için bir işleyici (handler) tanımlayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa, başka bir flow ya da paywall görüntüleyecek bir buton ekleyebilirsiniz: ```kotlin class MyAdaptyUIFlowsEventsObserver : AdaptyUIFlowsEventsObserver { override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { when (action.action) { "openNewFlow" -> { // Display another flow or paywall } } } else -> Unit } } } // Set up the observer AdaptyUI.setFlowsEventsObserver(MyAdaptyUIFlowsEventsObserver()) ``` </SDKv4> <SDKv3> :::warning **Yalnızca satın almalar ve geri yüklemeler otomatik olarak işlenir.** Paywallları kapatmak veya bağlantı açmak gibi diğer tüm buton işlemleri, uygulama kodunda uygun yanıtların uygulanmasını gerektirir. ::: Adapty paywall builder kullanarak paywall oluşturuyorsanız, butonları doğru şekilde ayarlamak kritik önem taşır: 1. [Paywall builder'a bir buton ekleyin](paywall-buttons) ve bu butona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi işlemek için uygulamanıza kod yazın. Bu kılavuz, kodunuzda özel ve önceden tanımlanmış eylemlerin nasıl ele alınacağını gösterir. ## AdaptyUIPaywallsEventsObserver'ı ayarlayın \{#set-up-the-adaptyuipaywallseventsobserver\} Paywall aksiyonlarını yönetmek için `AdaptyUIPaywallsEventsObserver` arayüzünü uygulamanız ve `AdaptyUI.setPaywallsEventsObserver()` ile kurmanız gerekir. Bu işlem, genellikle ana activity'nizde veya uygulama başlatma sırasında, uygulama yaşam döngüsünün erken aşamasında yapılmalıdır. ```kotlin // In your app initialization AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## Paywallları kapatın \{#close-paywalls\} Paywallınızı kapatacak bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Close** aksiyonunu atayın. 2. Uygulama kodunuzda, paywallı kapatan `close` aksiyonu için bir işleyici uygulayın. :::info Kotlin Multiplatform SDK'da `CloseAction` ve `AndroidSystemBackAction` varsayılan olarak paywallı kapatır. Ancak gerekirse bu davranışı kodunuzda değiştirebilirsiniz. Örneğin, bir paywallı kapatmak başka bir paywallın açılmasını tetikleyebilir. ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { AdaptyUIAction.CloseAction, AdaptyUIAction.AndroidSystemBackAction -> view.dismiss() } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` [`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform) kullanıyorsanız `view.dismiss()` çağrısının bir etkisi yoktur — görünüm KMP yığını üzerinden değil, doğrudan layout'unuza gömülüdür. Bunun yerine görünümü layout'unuzdan kaldırın ve üzerinde `dispose()` çağrısı yapın. ## Paywall'lardan URL açın \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı (ör. kullanım koşulları ve satın alma geri yükleme) eklemek istiyorsanız paywall builder'a bir **Link** öğesi ekleyin ve bunu **Open URL** aksiyonuyla düğmeleri yönettiğiniz gibi işleyin. ::: Paywallınızdan bir bağlantı açan bir düğme eklemek için (ör. **Terms of use** veya **Privacy policy**): 1. Paywall builder'da bir düğme ekleyin, **Open URL** aksiyonunu atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` aksiyonu için bir işleyici uygulayın. :::info Kotlin Multiplatform SDK'da `OpenUrlAction`, açılması gereken URL'yi sağlar. URL açmayı yönetmek için özel mantık uygulayabilirsiniz; örneğin bir onay iletişim kutusu gösterebilir veya uygulamanızın tercih ettiği URL yönetim yöntemini kullanabilirsiniz. ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver( private val uriHandler: UriHandler ) : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.OpenUrlAction -> { // Show confirmation dialog before opening URL mainUiScope.launch { val selectedAction = view.showDialog( title = "Open URL?", content = action.url, primaryActionTitle = "Cancel", secondaryActionTitle = "Open" ).getOrNull() when (selectedAction) { AdaptyUIDialogActionType.PRIMARY -> { // User cancelled } AdaptyUIDialogActionType.SECONDARY -> { // User confirmed - open URL uriHandler.openUri(action.url) } else -> Unit } } } } } } // Set up the observer with UriHandler AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver(uriHandler)) ``` ## Uygulamaya giriş yapın \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve buna "login" ID'siyle **Custom** aksiyon atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan özel aksiyon için bir işleyici uygulayın. ```kotlin class MyAdaptyUIObserver : AdaptyUIObserver { override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { if (action.action == "login") { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } ``` ## Özel aksiyonları yönetin \{#handle-custom-actions\} Başka aksiyonları yöneten bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin, **Custom** aksiyonunu atayın ve bir ID verin. 2. Uygulama kodunuzda, oluşturduğunuz aksiyon ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa başka bir paywall açan bir düğme ekleyebilirsiniz: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { when (action.action) { "login" -> { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` </SDKv3> --- # File: kmp-handling-events --- --- title: "Flow ve paywall olaylarını işleme - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda flow ve paywall olaylarını işleyin." --- <SDKv4> :::important Bu kılavuz; satın alma, geri yükleme, ürün seçimi ve flow görüntüleme için olay işlemeyi kapsar. Ayrıca düğme işlemeyi de (flow'u kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [flow aksiyonlarını işleme kılavuzumuza](kmp-handle-paywall-actions) bakın. ::: [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) ile yapılandırılan flow'lar ve paywaller, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; düğme tıklamalarını (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve satın alma işlemleriyle ilgili bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Mobil uygulamanızdaki flow ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIFlowsEventsObserver` arayüzü yöntemlerini uygulayın ve gözlemcinizi `AdaptyUI.setFlowsEventsObserver()` ile kaydedin. Bazı yöntemlerin yaygın senaryoları otomatik olarak ele alan varsayılan uygulamaları bulunur; bu nedenle yalnızca değiştirmek istediğiniz yöntemleri geçersiz kılın: ```kotlin showLineNumbers title="Kotlin" AdaptyUI.setFlowsEventsObserver(object : AdaptyUIFlowsEventsObserver { // override only the methods you want to change }) ``` :::note Bu metodlar, flow olaylarına yanıt vermek için özel mantığınızı eklediğiniz yerlerdir. Flow'u kapatmak için `view.dismiss()` kullanabilir ya da ihtiyaç duyduğunuz başka özel davranışları uygulayabilirsiniz. `dismiss()` fonksiyonunun bir suspend fonksiyonu olduğunu unutmayın — bir callback içinde, observer'ın `mainUiScope`'unu kullanarak çağırın: `mainUiScope.launch { view.dismiss() }`. ::: ### Kullanıcı tarafından tetiklenen olaylar #### Flow'un görünmesi ve kaybolması \{#flow-appearance-and-disappearance\} Bir flow göründüğünde veya kaybolduğunda şu metodlar çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidAppear(view: AdaptyUIFlowView) { // Handle flow appearance // You can track analytics or update UI here } override fun flowViewDidDisappear(view: AdaptyUIFlowView) { // Handle flow disappearance // You can track analytics or update UI here } ``` :::note - iOS'ta, `flowViewDidAppear` aynı zamanda kullanıcı bir flow içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve bir web paywall uygulama içi tarayıcıda açıldığında da tetiklenir. - iOS'ta, `flowViewDidDisappear` aynı zamanda bir flow'dan uygulama içi tarayıcıda açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda da tetiklenir. ::: <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Flow appeared { // No additional data } // Flow disappeared { // No additional data } ``` </Details> #### Ürün seçimi \{#product-selection\} Bir kullanıcı satın alma için ürün seçerse bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidSelectProduct(view: AdaptyUIFlowView, productId: String) { // Handle product selection // You can update UI or track analytics here } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> #### Satın alma başlatıldı \{#started-purchase\} Bir kullanıcı satın alma sürecini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidStartPurchase(view: AdaptyUIFlowView, product: AdaptyPaywallProduct) { // Handle purchase start // You can show loading indicators or track analytics here } ``` :::note [Observer modunda](kmp-present-flows-in-observer-mode), bir flow'dan başlatılan satın almalar `AdaptyUIObserverModeResolver`'ınıza iletilir. ::: <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### Başarılı, iptal edilmiş veya bekleyen satın alma \{#successful-canceled-or-pending-purchase\} Bir satın alma tamamlandığında bu metot çağrılır. Varsayılan olarak hiçbir şey yapmaz — satın alma sonrasında siz kapatana kadar flow açık kalır; bu nedenle kullanıcı erişim kazandığında `view.dismiss()` metodunu kendiniz çağırmanız gerekir: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFinishPurchase( view: AdaptyUIFlowView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { when (purchaseResult) { is AdaptyPurchaseResult.Success -> { // Check if user has access to premium features if (purchaseResult.profile.accessLevels["premium"]?.isActive == true) { mainUiScope.launch { view.dismiss() } } } AdaptyPurchaseResult.Pending -> { // Handle pending purchase (e.g., user will pay offline with cash) } AdaptyPurchaseResult.UserCanceled -> { // Handle user cancellation } } } ``` <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } // User canceled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCanceled" } } ``` </Details> Başarılı satın alım durumunda flow ekranını kapatmanızı öneririz. #### Başarısız satın alım \{#failed-purchase\} Bir satın alım hata nedeniyle başarısız olursa bu metot çağrılır. Bu durum; StoreKit/Google Play Billing hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptalleri bu metodu değil, iptal sonucuyla birlikte `flowViewDidFinishPurchase`'ı tetikler; bekleyen ödemeler ise bu metodu tetiklemez. ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFailPurchase( view: AdaptyUIFlowView, product: AdaptyPaywallProduct, error: AdaptyError ) { // Add your purchase failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> #### Geri yükleme başlatıldı \{#started-restore\} Bir kullanıcı geri yükleme işlemini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidStartRestore(view: AdaptyUIFlowView) { // Handle restore start // You can show loading indicators or track analytics here } ``` #### Başarılı geri yükleme \{#successful-restore\} Bir satın alma işlemi başarıyla geri yüklenirse bu metot çağrılır. Varsayılan olarak hiçbir şey yapmaz — siz kapatana kadar geri yükleme sonrasında flow açık kalır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFinishRestore(view: AdaptyUIFlowView, profile: AdaptyProfile) { // Add your successful restore handling logic here // For example: show success message, update UI, or dismiss the flow // Check if user has access to premium features if (profile.accessLevels["premium"]?.isActive == true) { mainUiScope.launch { view.dismiss() } } } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> Kullanıcı gerekli `accessLevel`'a sahipse ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](subscription-status) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olursa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFailRestore(view: AdaptyUIFlowView, error: AdaptyError) { // Add your restore failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> #### Web ödeme navigasyonu tamamlama \{#web-payment-navigation-completion\} Bir kullanıcı [web paywall](web-paywall) aracılığıyla satın alma işlemini başlatırsa bu metot çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFinishWebPaymentNavigation( view: AdaptyUIFlowView, product: AdaptyPaywallProduct?, error: AdaptyError? ) { if (error != null) { // Handle web payment navigation error } else { // Handle successful web payment navigation } } ``` <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Başarılı web ödeme navigasyonu { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Başarısız web ödeme navigasyonu { "product": null, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ``` </Details> ### Veri Alma ve Render Etme \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürünleri iletmezseniz, AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa, AdaptyUI hatayı şu metodu çağırarak bildirir: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidFailLoadingProducts(view: AdaptyUIFlowView, error: AdaptyError) { // Add your product loading failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> #### Render ve çalışma zamanı hataları \{#rendering-and-runtime-errors\} Arayüz render edilirken bir hata oluşursa ya da satın alma dışında başka bir çalışma zamanı hatası meydana gelirse, bu metot aracılığıyla bildirilir. Varsayılan olarak hata durumunda flow kapatılır — flow'u açık tutmak veya kendi işleme mantığınızı eklemek için bu metodu geçersiz kılın: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidReceiveError(view: AdaptyUIFlowView, error: AdaptyError) { // Handle the error // The default implementation dismisses the flow; // once you override this method, dismissal is up to you } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render flow interface", "details": { "underlyingError": "Invalid flow configuration" } } } ``` </Details> Normal koşullarda bu tür hatalar oluşmamalıdır; eğer biriyle karşılaşırsanız lütfen bize bildirin. #### Analytics olayları \{#analytics-events\} `flowViewDidReceiveAnalyticEvent` callback'i, bir flow'dan gelen özel analitik olaylar için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmediğinden, bunu uygulamanıza gerek yoktur: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidReceiveAnalyticEvent( view: AdaptyUIFlowView, name: String, paramsJsonString: String ) { // Reserved for custom analytic events from a flow } ``` ### Navigasyon \{#navigation\} #### Android sistem geri butonu \{#android-system-back-button\} Varsayılan olarak, bir flow Android sistem geri butonu veya geri hareketiyle kapatılamaz — varsayılan `flowViewDidPerformAction` implementasyonu flow'u yalnızca `CloseAction` ile kapatır ve `AndroidSystemBackAction`'ı yok sayar; bu nedenle kullanıcı, flow'dan sizin belirlediğiniz bir yol üzerinden çıkar: örneğin bir **Close** butonu veya builder'daki bir `on_device_back` aksiyonu. Sistem geri butonu ile flow'u kapatmak istiyorsanız aksiyonu kendiniz ele alın: ```kotlin showLineNumbers title="Kotlin" override fun flowViewDidPerformAction(view: AdaptyUIFlowView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> mainUiScope.launch { view.dismiss() } // default behavior is AdaptyUIAction.AndroidSystemBackAction -> mainUiScope.launch { view.dismiss() } // not handled by default is AdaptyUIAction.OpenUrlAction -> AdaptyUI.openWebUrl(action.url, action.openIn) // default behavior else -> Unit } } ``` [Flow aksiyonlarını yönetme kılavuzuna](kmp-handle-paywall-actions) tüm aksiyonların listesi için bakın. </SDKv4> <SDKv3> [Paywall Builder](adapty-paywall-builder) ile yapılandırılmış paywalllar, satın alma yapmak veya geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; düğme basışlarını (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili aksiyonlara dair bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. :::warning Bu kılavuz yalnızca **yeni Paywall Builder paywallları** içindir. ::: Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyUIPaywallsEventsObserver` arayüz metotlarını uygulayın. Bazı metotların, yaygın senaryoları otomatik olarak işleyen varsayılan uygulamaları mevcuttur. :::note Bu metotlar, paywall olaylarına özel mantığınızı eklediğiniz yerlerdir. Paywallı kapatmak için `view.dismiss()` kullanabilir ya da ihtiyacınıza göre herhangi bir özel davranış uygulayabilirsiniz. ::: ## Kullanıcı kaynaklı olaylar \{#user-generated-events\} ### Paywallın görünmesi ve kaybolması \{#paywall-appearance-and-disappearance\} Bir paywall belirdiğinde veya kaybolduğunda bu metodlar çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance // You can track analytics or update UI here } override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance // You can track analytics or update UI here } ``` :::note - iOS'ta, kullanıcı bir paywall içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) tıkladığında ve uygulama içi tarayıcıda bir web paywall açıldığında `paywallViewDidAppear` da çağrılır. - iOS'ta, bir paywalldan açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button) uygulama içi tarayıcıdan ekranda kaybolduğunda `paywallViewDidDisappear` da çağrılır. ::: <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Paywall appeared { // No additional data } // Paywall disappeared { // No additional data } ``` </Details> ### Ürün seçimi \{#product-selection\} Kullanıcı satın almak üzere bir ürün seçtiğinde bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { // Handle product selection // You can update UI or track analytics here } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> ### Satın alma başlatıldı \{#started-purchase\} Kullanıcı satın alma sürecini başlattığında bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start // You can show loading indicators or track analytics here } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> ### Başarılı, iptal edilmiş veya bekleyen satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olduğunda bu metod çağrılır. Varsayılan olarak, kullanıcı tarafından iptal edilmedikçe paywallı otomatik olarak kapatır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { when (purchaseResult) { is AdaptyPurchaseResult.Success -> { // Check if user has access to premium features if (purchaseResult.profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } AdaptyPurchaseResult.Pending -> { // Handle pending purchase (e.g., user will pay offline with cash) } AdaptyPurchaseResult.UserCanceled -> { // Handle user cancellation } } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } // User canceled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCanceled" } } ``` </Details> Başarılı satın alma durumunda paywall ekranını kapatmanızı öneririz. ### Başarısız satın alma \{#failed-purchase\} Bir hata nedeniyle satın alma başarısız olduğunda bu metod çağrılır. Bu durum; StoreKit/Google Play Billing hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcının iptal etmesi durumunda ise bu metod değil, iptal sonucuyla birlikte `paywallViewDidFinishPurchase` tetiklenir; bekleyen ödemeler bu metodu tetiklemez. ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError ) { // Add your purchase failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> ### Geri yükleme başlatıldı \{#started-restore\} Kullanıcı geri yükleme sürecini başlattığında bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartRestore(view: AdaptyUIPaywallView) { // Handle restore start // You can show loading indicators or track analytics here } ``` ### Başarılı geri yükleme \{#successful-restore\} Satın alma geri yükleme başarılı olduğunda bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here // For example: show success message, update UI, or dismiss paywall // Check if user has access to premium features if (profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](subscription-status) konusuna bakın. ### Başarısız geri yükleme \{#failed-restore\} `Adapty.restorePurchases()` başarısız olduğunda bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> ### Web ödeme navigasyonu tamamlandı \{#web-payment-navigation-completion\} Kullanıcı [web paywall](web-paywall) üzerinden satın alma sürecini başlattığında bu metod çağrılır: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishWebPaymentNavigation( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError? ) { if (error != null) { // Handle web payment navigation error } else { // Handle successful web payment navigation } } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful web payment navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed web payment navigation { "product": null, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ``` </Details> ## Veri çekme ve render etme \{#data-fetching-and-rendering\} ### Ürün yükleme hataları \{#product-loading-errors\} Başlatma sırasında ürünleri siz geçmezseniz AdaptyUI gerekli nesneleri sunucudan kendi alır. Bu işlem başarısız olursa AdaptyUI hatayı bu metodu çağırarak bildirir: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> ### Render hataları \{#rendering-errors\} Arayüz render edilirken bir hata oluşursa bu metod aracılığıyla bildirilir: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error // In a normal situation, such errors should not occur // If you come across one, please let us know } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> Normal şartlarda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin. </SDKv3> --- # File: kmp-use-fallback-paywalls --- --- title: "Kotlin Multiplatform - Yedek paywall kullanımı" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucularına erişilemediğinde durumu yönetin" --- Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek yapılandırma dosyasını uygulamanıza ekleyin. * Hedef platformunuz Android ise yedek yapılandırma dosyasını `android/app/src/main/assets/` klasörüne taşıyın. * Hedef platformunuz iOS ise yedek JSON dosyasını proje paketinize ekleyin. (**File** -> **Add Files to YourProjectName**) 2. Hedef flow, paywall veya onboarding'i almadan **önce** `.setFallback` metodunu çağırın. 3. Hedef platformunuza göre `assetId` parametresini ayarlayın. * Android: `assets` dizinine göreli dosya yolunu kullanın. * iOS: Tam dosya adını kullanın. ```kotlin showLineNumbers Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` :::important `setFallback`, SDK'nın hedef flow, paywall veya onboarding'i getirmesinden önce çalıştırılmalıdır. ::: Parametreler: | Parametre | Açıklama | | :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **assetId** | Yedek yapılandırma dosya adı (iOS). <br /> `assets` dizinine göreli yedek yapılandırma dosya yolu (Android). | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: kmp-localizations-and-locale-codes --- --- title: "Kotlin Multiplatform SDK'da yerelleştirmeleri ve yerel ayar kodlarını kullanın" description: "Kotlin Multiplatform uygulamanızda küresel bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin." --- <SDKv4> ## Bu neden önemli \{#why-this-is-important\} Adapty bir flow için yerelleştirme seçerken ve özel bir paywall için remote config okurken locale kodları devreye girer. Locale kodları karmaşık olabilir ve platformdan platforma farklılık gösterebilir; bu nedenle Adapty desteklediği her platformda tek bir dahili standarda dayanır. Bu standardı anlamak, kullanıcının hangi yerelleştirmeyi alacağını öngörmenize yardımcı olur. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için hafif değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, tire ile ayrılmış küçük harf alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel kod eşleştirme \{#locale-code-matching\} Adapty, kullanıcının yerel ayarıyla eşleşen yerelleştirmeyi ararken şu adımları izler: 1. Yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgilerle (`-`) değiştirilir 2. Adapty, tam olarak eşleşen yerel kod için yerelleştirmeyi arar 3. Eşleşme bulunamazsa, Adapty ilk kısa çizgiden önceki alt dizeyi alır (`pt-br` için `pt`) ve eşleşen yerelleştirmeyi arar 4. Yine eşleşme bulunamazsa, Adapty varsayılan `en` yerelleştirmesini döndürür Bu sayede `'pt_BR'`, `pt-BR` ve `pt-br` hepsi aynı yerelleştirmeye karşılık gelir. ## Yerelleştirmeleri Uygulamak \{#implementing-localizations\} SDK v4'te bir flow çekerken locale kodu göndermenize gerek yok. - **Flow Builder ve Paywall Builder paywallları**: Adapty, yerelleştirmeyi cihazdan ve builder'da yapılandırdığınız yerelleştirmelerden otomatik olarak çözümler. Flow'u `createFlowView` ile render edin — locale koduna gerek yok. - **Özel (remote config) paywalllar**: `getFlow`, yapılandırılmış her yerelleştirmeyi `flow.remoteConfigs` içinde döndürür. Her giriş, bir `locale` kodu ve `dataMap` içeren bir `AdaptyRemoteConfig`'tir. Kullanıcıyla eşleşen girişi kendi fallback mantığınızla seçin: ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") .onSuccess { flow -> val config = flow.remoteConfigs.firstOrNull { it.locale == "en" } ?: flow.remoteConfigs.firstOrNull() // read your values from config?.dataMap } .onError { error -> // handle the error } ``` Yukarıdaki locale kod eşleştirme kuralları, Adapty'nin her remote config üzerinde saklanan `locale` kodlarını nasıl normalleştirdiğini açıklar. </SDKv4> <SDKv3> ## Bu neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır — örneğin, uygulamanızın mevcut yerelleştirmesi için doğru paywall'ı almaya çalışırken. Yerel ayar kodları karmaşık olduğundan ve platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlar için dahili bir standarda dayanıyoruz. Ancak bu kodlar karmaşık olduğu için, doğru yerelleştirmeyi almak üzere sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; böylece her zaman beklediğinizi alırsınız. ## Adapty'de locale kodu standardı \{#locale-code-standard-at-adapty\} Adapty, locale kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Birkaç örnek: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan yerel ayar koduyla bir çağrı aldığında ve paywall için ilgili yerelleştirmeyi aramaya başladığında şu adımlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`), kısa çizgiyle (`-`) değiştirilir. 2. Tam olarak eşleşen yerel ayar koduna sahip yerelleştirme aranır. 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve bu kodla eşleşen yerelleştirme aranır. 4. Yine eşleşme bulunamazsa varsayılan `en` yerelleştirmesi döndürülür. Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alacaktır. ## Lokalizasyonları uygulama: önerilen yöntem \{#implementing-localizations-recommended-way\} Lokalizasyonlarla ilgileniyorsanız, büyük ihtimalle projenizdeki lokalize edilmiş string kaynaklarıyla zaten çalışıyorsunuzdur. Eğer öyleyse, her kaynak dosyanıza ilgili lokalizasyon için Adapty locale kodu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde çekebilirsiniz: ```kotlin showLineNumbers // 1. Adapty yerel ayar kodunu Compose Multiplatform kaynaklarınıza ekleyin /* composeResources/values/strings.xml (varsayılan — İngilizce) */ <string name="adapty_paywalls_locale">en</string> /* composeResources/values-es/strings.xml (İspanyolca) */ <string name="adapty_paywalls_locale">es</string> /* composeResources/values-pt-rBR/strings.xml (Portekizce — Brezilya) */ <string name="adapty_paywalls_locale">pt-br</string> // 2. Yerel ayar kodunu çıkarın ve kullanın suspend fun fetchPaywall() { val locale = getString(Res.string.adapty_paywalls_locale) Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = locale ).onSuccess { paywall -> // istenen paywall }.onError { error -> // hatayı işle } } ``` Bu sayede uygulamanızın her kullanıcısı için hangi yerelleştirmenin alınacağı üzerinde tam kontrol sahibi olursunuz. Compose Multiplatform kaynakları kullanmıyorsanız, aynı fikir kullandığınız herhangi bir yerelleştirme kütüphanesi için de geçerlidir (örneğin, [moko-resources](https://github.com/icerockdev/moko-resources)) — Adapty yerel ayar kodunu her yerel ayarın kaynak paketinde bir dize olarak saklayın ve SDK'yı çağırmadan önce okuyun. ## Yerelleştirmeleri uygulama: alternatif yol \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça dil kodu tanımlamadan da benzer (ancak aynı değil) sonuçlar elde edebilirsiniz. Bu yaklaşım, dil kodunu doğrudan cihazdan çıkarmak anlamına gelir; ancak `commonMain` içinde ortak bir dil kodu API'si olmadığından `expect`/`actual` bildirimleri gereklidir: ```kotlin showLineNumbers // commonMain expect fun currentLocaleTag(): String // androidMain actual fun currentLocaleTag(): String = Locale.getDefault().toLanguageTag() // iosMain actual fun currentLocaleTag(): String = NSLocale.currentLocale.localeIdentifier // commonMain — pass the locale code to Adapty suspend fun fetchPaywall() { Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = currentLocaleTag() ).onSuccess { paywall -> // istenen paywall }.onError { error -> // hatayı işle } } ``` Birkaç nedenden dolayı bu yaklaşımı önermiyoruz: 1. iOS'ta kullanıcının tercih ettiği dil ile cihazın bölgesel yerel ayarı aynı değildir. `NSLocale.currentLocale.localeIdentifier`, kullanıcının uygulamanızı gerçekte hangi dilde okuduğuyla örtüşmeyebilecek bölgesel yerel ayarı döndürür. Yerelleştirilmiş string dosyaları kullanan iOS uygulamaları, her ikisini birleştirmek için Apple'ın çözümleme mantığına dayanır; bu da yukarıdaki önerilen yaklaşımla doğrudan çalışır. 2. Cihazın tam olarak ne döndüreceğini ve bunun Adapty'deki bir yerelleştirmeyle eşleşip eşleşmeyeceğini tahmin etmek güçtür. Cihaz yerel ayarı, Adapty'de yapılandırmadığınız uzantılar veya bölge kodları içerebilir; bu durumda SDK, ilk alt etikete göre eşleşmeye ya da nihayetinde `en` diline geri döner. Bu yaklaşımı kullanmaya karar verirseniz, ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun. </SDKv3> --- # File: kmp-web-paywalls --- --- title: "Kotlin Multiplatform SDK'da web paywalllarını uygulama" description: "Mağaza ücretleri ve denetimleri olmadan ödeme almak için web paywall kurun." --- :::important Başlamadan önce [kontrol panelinde web paywallınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.15 veya sonraki bir sürümünü yüklediğinizden emin olun. ::: ## Web paywalllarını açma \{#open-web-paywalls\} Kendi geliştirdiğiniz bir paywall kullanıyorsanız web paywalllarını SDK metoduyla yönetmeniz gerekir. `openWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'ı yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcıların uygulamaya ne zaman döndüğünü izler ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `getProfile` ister. Bu sayede ödeme başarılı olup erişim hakları güncellendiyse abonelik uygulamada neredeyse anında etkinleşir. :::note Kullanıcılar uygulamaya döndükten sonra profil güncellemelerini yansıtmak için UI'ı yenileyin. Adapty, profil güncelleme etkinliklerini alıp işleyecektir. ::: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall(product = product).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` :::note `openWebPaywall` metodunun iki versiyonu bulunmaktadır: 1. `openWebPaywall(product = product)` — URL'leri paywall'a göre oluşturur ve ürün verilerini de URL'lere ekler. 2. `openWebPaywall(paywall = paywall)` — URL'leri paywall'a göre oluşturur, ancak ürün verilerini URL'lere eklemez. Adapty paywallındaki ürünler web paywallındakilerden farklıysa bunu kullanın. SDK v4'te `paywall` parametresinin yerini, `flow.paywalls` içindeki paywall varyantlarından biri olan `AdaptyFlowPaywall` alan bir `flowPaywall` parametresi almıştır. [Migrasyon kılavuzuna](migration-to-kmp-sdk-v4) bakın. ::: ## Web paywalllarını uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} Web paywalllar varsayılan olarak harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sunmak için web paywallları uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanız içinde gösterilir ve kullanıcılar uygulama değiştirmeden işlemi tamamlayabilir. Bunu etkinleştirmek için `openIn` parametresini `AdaptyWebPresentation.IN_APP_BROWSER` olarak ayarlayın: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall( product = product, openIn = AdaptyWebPresentation.IN_APP_BROWSER // default – EXTERNAL_BROWSER ).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` --- # File: kmp-present-flows-in-observer-mode --- --- title: "Observer modunda flow'ları sunma - Kotlin Multiplatform" description: "Kotlin Multiplatform uygulamanızda Observer modunda flow'ları ve Paywall Builder paywall'larını sunun, satın almaları kendi kodunuzla yönetin." --- Builder ile bir flow veya paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir flow veya paywall, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu bölüm yalnızca [Observer modu](observer-vs-full-mode) için geçerlidir. Observer modunda çalışmıyorsanız [Flow'ları ve paywall'ları görüntüleme](kmp-present-paywalls) konusuna bakın. ::: :::info Bu özellik, Adapty Kotlin Multiplatform SDK 4.0 (beta) veya sonrasını gerektirir — daha önce yalnızca native iOS ve Android SDK'larında mevcuttu. Yükseltmek için [migration rehberine](migration-to-kmp-sdk-v4) bakın. ::: <details> <summary>Flow sunmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. Adapty'nin [App Store ile](initial_ios) ve [Google Play ile](initial-android) başlangıç entegrasyonunu yapın. 2. Adapty SDK'yı yükleyin ve yapılandırın. Yapılandırma builder'ında `withObserverMode(true)` çağırdığınızdan emin olun. [Kotlin Multiplatform SDK kurulum kılavuzuna](sdk-installation-kotlin-multiplatform#activate-adapty-sdk) bakın. 3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product). 4. [Builder'larda flow'lar veya paywall'lar yapılandırın](create-paywall) ve bunlara ürünler atayın. 5. [Placement'lar oluşturun ve flow'larınızı ya da paywall'larınızı bunlara atayın](create-placement). 6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını çekin](kmp-get-pb-paywalls). </details> Observer modunda SDK, satın alma işlemlerini sizin adınıza gerçekleştirmez. Kullanıcı Adapty tarafından render edilen bir flow veya paywall'da satın alma ya da geri yükleme düğmesine dokunduğunda, SDK `AdaptyUIObserverModeResolver`'ınızı çağırır — satın alma veya geri yükleme işlemini orada kendi kodunuzla gerçekleştirin. 1. `AdaptyUIObserverModeResolver` arayüzünü uygulayın: ```kotlin showLineNumbers import com.adapty.kmp.AdaptyUIObserverModeResolver import com.adapty.kmp.models.AdaptyPaywallProduct import com.adapty.kmp.models.AdaptyUIFlowView class MyObserverModeResolver : AdaptyUIObserverModeResolver { override fun observerModeDidInitiatePurchase( view: AdaptyUIFlowView, product: AdaptyPaywallProduct, onStartPurchase: () -> Unit, onFinishPurchase: () -> Unit ) { onStartPurchase() // the view shows its loading indicator // make the purchase with your own code, // then report the transaction to Adapty and call: onFinishPurchase() // the view hides the loading indicator } override fun observerModeDidInitiateRestore( view: AdaptyUIFlowView, onStartRestore: () -> Unit, onFinishRestore: () -> Unit ) { onStartRestore() // restore purchases with your own code, then: onFinishRestore() } } ``` `observerModeDidInitiatePurchase` metodu, kullanıcının bir satın alma işlemi başlattığını; `observerModeDidInitiateRestore` ise kullanıcının geri yükleme işlemi başlattığını size bildirir. Buna yanıt olarak özel satın alma veya geri yükleme flow'unuzu tetikleyin. Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi doğru flow davranışı için gereklidir: | Callback | Description | | :----------------- | :------------------------------------------------------------------------------- | | onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | | onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. | Flow, kodunuz çalışırken açık kalır — başarılı bir satın alma veya geri yükleme işleminin ardından onu kendiniz kapatmanız gerekir. 2. Herhangi bir ekranı göstermeden önce resolver'ı kaydedin: ```kotlin showLineNumbers import com.adapty.kmp.AdaptyUI AdaptyUI.setObserverModeResolver(MyObserverModeResolver()) ``` Kayıtlı bir resolver olmadan, flow görünümünün satın alma işlemini kodunuza aktarma yolu yoktur ve kullanıcı satın alma düğmesine bastığında hiçbir şey olmaz. 3. Flow view'u her zamanki gibi oluşturup sunun: [flow'u çekip view'unu oluşturun](kmp-get-pb-paywalls), ardından [sunun](kmp-present-paywalls). Ekstra parametre gerekmez — resolver kaydedildikten sonra, Adapty tarafından render edilen her flow veya paywall, satın alma ve geri yüklemeleri bu resolver üzerinden yönlendirir. :::warning [İşlemi raporlamayı ve paywall ile ilişkilendirmeyi](report-transactions-observer-mode-kmp) unutmayın. Aksi takdirde Adapty işlemi tanımaz ve satın almanın kaynak paywall'ını belirleyemez. ::: --- # File: kmp-troubleshoot-paywall-builder --- --- title: "Kotlin Multiplatform SDK'da Paywall Builder Sorunlarını Giderme" description: "Kotlin Multiplatform SDK'da Paywall Builder sorunlarını giderme" --- Bu kılavuz, Kotlin Multiplatform SDK'da Adapty Paywall Builder ile tasarlanmış paywall'ları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `createPaywallView` metodu paywall görünümü oluşturmayı başaramıyor ya da paywall'ın görünüm yapılandırması yok. **Neden**: Paywall, Paywall Builder'da cihazda gösterim için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. Bir paywall'ın görünüm yapılandırmasına sahip olup olmadığını `AdaptyPaywall` nesnesindeki `hasViewConfiguration` özelliğini kullanarak da kontrol edebilirsiniz. <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Paywall görüntülenme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntülenme sayısı beklenenin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (SDK v4+) / `logShowPaywall` çağrısı yapıyor olabilirsiniz; Paywall Builder veya Flow Builder kullanıyorsanız bu, görüntülenme sayısını iki katına çıkarır. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitik otomatik olarak izlenir, dolayısıyla bu metodu çağırmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (SDK v4+) / `logShowPaywall` çağrısı yapmadığınızdan emin olun. --- # File: kmp-implement-paywalls-manually --- --- title: "Kotlin Multiplatform SDK'da paywallları manuel olarak uygulayın" description: "Adapty SDK ile Kotlin Multiplatform uygulamanızda paywallları manuel olarak nasıl uygulayacağınızı öğrenin." --- ## Satın alma işlemlerini kabul etme \{#accept-purchases\} Kendiniz uyguladığınız paywalllarla çalışıyorsanız, `makePurchase` yöntemini kullanarak satın alma işlemlerinin yönetimini Adapty'ye devredebilirsiniz. Bu sayede tüm kullanıcı senaryolarını biz yönetiriz; sizin yalnızca satın alma sonuçlarını işlemeniz yeterlidir. :::important `makePurchase`, Adapty kontrol panelinde oluşturulan ürünlerle çalışır. [Hızlı başlangıç kılavuzunu](quickstart) takip ederek kontrol panelinde ürünleri ve bunları alma yöntemlerini yapılandırdığınızdan emin olun. ::: <CustomDocCardList ids={['kmp-quickstart-manual', 'fetch-paywalls-and-products-kmp', 'present-remote-config-paywalls-kmp', 'kmp-making-purchases', 'kmp-restore-purchase', 'kmp-troubleshoot-purchases']} /> ## Observer modu \{#observer-mode\} Sıfırdan kendi satın alma işleme mantığınızı uygulamak istiyor ancak Adapty'nin gelişmiş analizlerinden yararlanmaya devam etmek istiyorsanız observer modunu kullanabilirsiniz. :::important Observer modu sınırlamalarını [buradan](observer-vs-full-mode) inceleyin. ::: <CustomDocCardList ids={['implement-observer-mode-kmp', 'report-transactions-observer-mode-kmp', 'kmp-troubleshoot-purchases']} /> --- # File: kmp-quickstart-manual --- --- title: "Kotlin Multiplatform SDK'da özel paywallınızda satın almaları etkinleştirin" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Kotlin Multiplatform paywalllarınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywalllarınıza nasıl entegre edeceğinizi açıklar. Paywall implementasyonu üzerinde tam kontrolü elinizde tutarken Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler. Bu kılavuz, Adapty Kotlin Multiplatform SDK v4 (beta) API'lerini kullanmaktadır. v3 kullanıyorsanız, karşılık gelen metod adları için [migration kılavuzuna](migration-to-kmp-sdk-v4) bakın. :::important **Bu kılavuz, özel paywall'lar uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız, [Adapty Flow Builder](kmp-quickstart-paywalls)'ı kullanın. Flow Builder ile no-code görsel editörde flow'lar oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlama \{#set-up-products\} Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünlere yalnızca paywalllar aracılığıyla ulaşılabilir; bu tasarım sayesinde uygulama koduna dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. SDK v4'te bir placement'a ait paywall varyantları bir **flow** nesnesi tarafından taşınır; bir flow çeker ve ürünlerini sorgularsınız. - [**Placement'lar**](placements) – uygulamanızda paywallların nerede ve ne zaman gösterileceği (`main`, `onboarding`, `settings` gibi). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yaklaşım A/B testi çalıştırmayı ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır. Özel paywall kullanıyor olsanız bile bu kavramları anladığınızdan emin olun. Temel olarak, bunlar uygulamanızda sattığınız ürünleri yönetmenin yoludur. Özel paywall'unuzu uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu kurulum, ürünlerinizi almanızı sağlar. Kontrol panelinde yapmanız gerekenleri anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetme \{#manage-users\} Backend kimlik doğrulaması ile veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve tanımlı kullanıcıları farklı şekilde ele alır. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik belirleme hızlı başlangıç kılavuzunu](kmp-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywallınız için ürünleri almak üzere şunları yapmanız gerekir: 1. [placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın. 2. Bu flow için `getPaywallProducts` metodunu kullanarak ürünler dizisini alın. ```kotlin showLineNumbers fun loadPaywall() { Adapty.getFlow(placementId = "YOUR_PLACEMENT_ID") .onSuccess { flow -> Adapty.getPaywallProducts(flow = flow) .onSuccess { products -> // Use products to build your custom paywall UI } .onError { error -> // Handle the error } } .onError { error -> // Handle the error } } ``` ## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\} Kullanıcı özel paywall'unuzda bir ürüne dokunduğunda, seçilen ürünle `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun purchaseProduct(product: AdaptyPaywallProduct) { Adapty.makePurchase(product = product) .onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } .onError { error -> // Handle the error } } ``` ## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik içeren tüm uygulamaların kullanıcılara satın almalarını geri yükleme imkânı sunmasını zorunlu kılar. Kullanıcı geri yükleme düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases() .onSuccess { profile -> // Restore successful, profile updated } .onError { error -> // Handle the error } } ``` ## Adım 4. Abonelik durumunu kontrol edin \{#step-4-check-the-subscription-status\} Satın alma veya geri yükleme işleminin ardından, paywall'ı gösterip göstermeyeceğinize ya da ücretli özellikleri açıp açmayacağınıza karar vermek için kullanıcının [access level](access-level) bilgisini kontrol edin. `makePurchase` ve `restorePurchases` metodları güncel profili zaten döndürür; uygulamanın başka bir yerinde mevcut duruma ihtiyaç duyduğunuzda `getProfile` metodunu kullanın: ```kotlin showLineNumbers fun checkPremiumAccess() { Adapty.getProfile() .onSuccess { profile -> val hasPremiumAccess = profile.accessLevels["premium"]?.isActive == true // Grant access to paid features if hasPremiumAccess is true } .onError { error -> // Handle the error } } ``` Abonelik durumunu kontrol etmenin ve gerçek zamanlı güncellemeleri dinlemek de dahil olmak üzere izlemenin daha fazla yolunu öğrenmek için bkz. [Abonelik durumunu kontrol etme](kmp-check-subscription-status). ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'unuz uygulamada gösterilmeye hazır. Paywall üzerinden bir test satın alması tamamlayabildiğinizi doğrulamak için satın almalarınızı [App Store sandbox](test-purchases-in-sandbox)'ta veya [Google Play Store](testing-on-android)'da test edin. Bunun üretim ortamında nasıl çalıştığını görmek için uygun hata yönetimi ve durum yönetimiyle satın alma işlemini gösteren örnek uygulamamızdaki [AppViewModel.kt](https://github.com/adaptyteam/AdaptySDK-KMP/blob/main/example/composeMultiplatformApp/composeApp/src/commonMain/kotlin/com/adapty/exampleapp/AppViewModel.kt) dosyasına bakabilirsiniz. --- # File: fetch-paywalls-and-products-kmp --- --- title: "Kotlin Multiplatform SDK'da remote config paywall'ları için paywall'ları ve ürünleri getirme" description: "Kullanıcı monetizasyonunu artırmak için Adapty Kotlin Multiplatform SDK'da paywall'ları ve ürünleri getirin." --- <SDKv4> Remote config ve özel paywallları sergilemeden önce bunlara ilişkin bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu lütfen unutmayın. **Flow Builder** veya **Paywall Builder**'da özelleştirilen flow'ları veya paywallları almak için rehberlik amacıyla [Flow'ları ve paywallları alma](kmp-get-pb-paywalls) bölümüne başvurun. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri içine ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow ya da paywall'ınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-kotlin-multiplatform). </details> ## Flow bilgilerini al \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'deki ürünlerin bir kombinasyonunu temsil eder. Bu çapraz platform ürünler, flow'lara ve paywall'lara entegre edilerek belirli mobil uygulama placement'larında gösterilmesine olanak tanır. Ürünleri göstermek için `getFlow` metodu ile [placement](placements)'larınızdan birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini sabit kodlamayın.** Sabit kodlamanız gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanızın bu değişiklikleri dinamik olarak ele alması gerekir—bir flow bugün iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getFlow( placementId = "YOUR_PLACEMENT_ID", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { flow -> // the requested flow }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirlediğiniz değerdir. | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla mücadele ettiğini düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu senaryoda kullanıcılar en son verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle ağ isteklerini azaltmak amacıyla oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, flow'ları ve paywallları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](kmp-use-fallback-paywalls). Flow'ları ve paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, her zaman en güncel flow ve paywall sürümüne ulaşmanızı sağlarken internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği ön planda tutar.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Ürün ID'lerini hardcode etmeyin! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünün tamamını göstermelidir. Hardcode etmeniz gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Bir `AdaptyFlow` nesnesi şunları içerir: flow tanımlayıcısı, paywall varyasyonları (`paywalls` — her biri kendi ürün tanımlayıcılarıyla), yapılandırılan her yerel ayar için bir giriş içeren `remoteConfigs` listesi ve diğer çeşitli özellikler. Flow için ürünleri almak üzere `getPaywallProducts(flow)` çağrısını kullanın. | :::note v4'te `getFlow` fonksiyonunun `locale` parametresi yoktur. `createFlowView` ile bir flow render ettiğinizde, yerelleştirme otomatik olarak çözümlenir. Özel paywalllar için tüm mevcut yerel ayarlar `flow.remoteConfigs` içinde birlikte döndürülür; kullanıcının cihazına veya uygulamanızın ayarına uyan yerel ayarı seçin. Ayrıntılar için [Yerelleştirmeler ve yerel ayar kodları](kmp-localizations-and-locale-codes) bölümüne bakın. ::: ## Ürünleri getir \{#fetch-products\} Flow'u aldıktan sonra, o flow'a karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(flow).onSuccess { products -> // the requested products }.onError { error -> // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) nesnelerinin listesi. | Kendi flow tasarımınızı uygularken, büyük olasılıkla [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) nesnesindeki bu özelliklere erişmeniz gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın dilinden değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş sürümünü görüntülemek için `product.price.localizedString` kullanın. Bu yerelleştirme, cihazın dil bilgisine dayanır. Fiyata sayı olarak erişmek için `product.price.amount` kullanabilirsiniz. Değer yerel para biriminde sağlanır. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (ör. hafta, ay, yıl vb.) görüntülemek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme, cihazın diline dayanır. Abonelik dönemini programatik olarak almak için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Buradan uzunluğu elde etmek amacıyla `unit` enum'ına erişebilirsiniz (DAY, WEEK, MONTH, YEAR veya UNKNOWN). `numberOfUnits` değeri, dönem birimi sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde ise `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için rozet veya başka bir gösterge kullanmak istiyorsanız `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, en fazla iki indirim aşaması içerebilir: ücretsiz deneme aşaması ve başlangıç fiyatı aşaması. Her aşama nesnesinde şu kullanışlı özellikler yer alır:<br/>• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerine sahip bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.<br/>• `price`: Sayı olarak ifade edilen indirimli fiyat. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın diline göre yerelleştirilmiş biçimde açıklayan bir dize. Örneğin üç günlük deneme teklifinde bu alanda `3 days` görünür.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarını bu özellikle alabilirsiniz. Teklifler için de önceki bölümde açıklandığı şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının diline göre biçimlendirilmiş, indirime ait abonelik dönemi. | ## Varsayılan kitle flow'u ile flow getirme işlemini hızlandırın \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu nedenle bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız olduğu ve kullanıcılarınızın zayıf bir internet bağlantısına sahip olduğu durumlarda, bir flow'u getirmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu ele almak için, belirtilen placement'ın **All Users** kitlesi için flow'unu getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products-kmp#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi `getFlow` metoduyla flow'u getirmek olduğunu anlamak çok önemlidir. :::warning Neden `getFlow` kullanmanızı öneriyoruz `getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecek) için farklı flow'lar göstermeniz gerekiyorsa, bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız gerekecek ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecek. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görecektir; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution verilerine veya kendi özel niteliklere dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Eğer daha hızlı flow getirme işleminden yararlanmak adına bu dezavantajları kabul etmeye hazırsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-kmp#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getFlowForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", fetchPolicy = AdaptyPaywallFetchPolicy.Default ).onSuccess { flow -> // the requested flow }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbelleğe alınmış veri mevcutsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerinden kaçınmak amacıyla oturum boyunca güvenle kullanabilirsiniz.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p> | </SDKv4> <SDKv3> Remote config ve özel paywallları göstermeden önce, bunlarla ilgili bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu lütfen unutmayın. Paywall Builder ile özelleştirilmiş paywallları almak için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](kmp-get-pb-paywalls) bölümüne bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. [Bir paywall oluşturun ve ürünleri paywall'unuza ekleyin](create-paywall) - Adapty Kontrol Paneli'nde. 3. [Placement'lar oluşturun ve paywall'unuzu placement'a ekleyin](create-placement) - Adapty Kontrol Paneli'nde. 4. [Adapty SDK'yı yükleyin](sdk-installation-kotlin-multiplatform) - mobil uygulamanıza. </details> ## Paywall bilgilerini getir \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'den gelen ürünlerin birleşimini temsil eder. Bu çok platformlu ürünler paywall'lara entegre edilerek belirli mobil uygulama placement'larında sergilenir. Ürünleri görüntülemek için `getPaywall` metodunu kullanarak [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan kodlamanız gereken tek ID, placement ID'sidir. Paywall'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak yönetmelidir; bugün bir paywall iki ürün döndürüyorsa ve yarın üç döndürüyorsa, kod değişikliği yapmadan hepsini gösterin. ::: ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK varsayılan olarak verileri sunucudan yüklemeye çalışır; başarısız olması durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri mevcutsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar mutlak en son verileri alamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek amacıyla oturum boyunca güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](kmp-use-fallback-paywalls). Paywall'ları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının kısıtlı olduğu durumlarda bile güvenilirliği sağlarken paywall'larınızın her zaman en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Ürün ID'lerini sabit kodlamayın! Paywall'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz denemeler gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız o 2 ürünü görüntülemelidir. Ancak daha sonra 3 ürün alırsanız, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünün tamamını görüntülemelidir. Sabit kodlamanız gereken tek şey placement ID'dir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'lerinin listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) nesnesi. | ## Ürünleri getir \{#fetch-products\} Paywall'ı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall).onSuccess { products -> // the requested products }.onError { error -> // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikleri içeren [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, büyük olasılıkla [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye başvurun. | Özellik | Açıklama | |----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Başlık** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın dil ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Fiyat** | Fiyatın yerelleştirilmiş halini görüntülemek için `product.price.localizedString` kullanın. Bu yerelleştirme cihazın dil bilgisine göre yapılır. Fiyata sayısal olarak erişmek için `product.price.amount` kullanabilirsiniz. Değer yerel para biriminde döndürülür. İlgili para birimi sembolünü almak için `product.price.currencySymbol` kullanın. | | **Abonelik Dönemi** | Dönemi (örn. hafta, ay, yıl vb.) görüntülemek için `product.subscriptionDetails?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın diline göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionDetails?.subscriptionPeriod` kullanın. Bu özellik üzerinden `unit` enum'una erişerek süreyi (DAY, WEEK, MONTH, YEAR veya UNKNOWN) öğrenebilirsiniz. `numberOfUnits` değeri ise dönem birimi sayısını verir. Örneğin üç aylık bir abonelikte `unit` özelliğinde `MONTH`, `numberOfUnits` özelliğinde `3` görürsünüz. | | **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini belirtmek için rozet veya başka bir gösterge kullanmak istiyorsanız `product.subscriptionDetails?.introductoryOfferPhases` özelliğine bakın. Bu liste, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere en fazla iki indirim aşaması içerebilir. Her aşama nesnesinde şu yararlı özellikler bulunur:<br/>• `paymentMode`: `FREE_TRIAL`, `PAY_AS_YOU_GO`, `PAY_UPFRONT` ve `UNKNOWN` değerlerini alan bir enum. Ücretsiz denemeler `FREE_TRIAL` türünde olur.<br/>• `price`: İndirimli fiyatın sayısal değeri. Ücretsiz denemeler için burada `0` değerini arayın.<br/>• `localizedNumberOfPeriods`: Teklifin süresini cihazın diline göre yerelleştirilmiş biçimde açıklayan bir metin. Örneğin üç günlük deneme teklifinde bu alanda `3 days` gösterilir.<br/>• `subscriptionPeriod`: Teklif döneminin ayrıntılarını ayrı ayrı almak için bu özelliği kullanabilirsiniz. Teklifler için bir önceki bölümde açıklanan şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının diline göre biçimlendirilmiş indirim abonelik dönemi. | ## Varsayılan kitle paywalli ile paywall getirmeyi hızlandırın \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywallınız olduğu durumlarda ve kullanıcılarınızın internet bağlantısı zayıfsa, bir paywallın getirilmesi istediğinizden daha uzun sürebilir. Bu tür durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın paywallini **All Users** kitlesi için getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak şunu bilmek önemlidir: önerilen yaklaşım, yukarıdaki [Paywall Bilgisini Getir](fetch-paywalls-and-products-kmp#fetch-paywall-information) bölümünde açıklanan `getPaywall` metoduyla paywalli getirmektir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Potansiyel geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların render edilemeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekecektir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görecektir; bu da ülkelere, pazarlama attribution'ına veya kendi özel nitelendirmelerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir. Bu dezavantajları kabul ederek daha hızlı paywall getirme işleminden yararlanmak istiyorsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-kmp#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin. ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) için tanımlayıcı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesi](add-remote-config-locale) için tanımlayıcı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p></p> | | **fetchPolicy** | varsayılan: `AdaptyPaywallFetchPolicy.Default` | <p>SDK, varsayılan olarak sunucudan veri yüklemeyi dener ve hata durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanmayı değerlendirebilirsiniz. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini azaltmak amacıyla güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını, yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.</p> | </SDKv3> --- # File: present-remote-config-paywalls-kmp --- --- title: "Kotlin Multiplatform SDK'da remote config ile tasarlanmış paywall'ı render etme" description: "Adapty Kotlin Multiplatform SDK'da kullanıcı deneyimini kişiselleştirmek için remote config paywall'larını nasıl sunacağınızı keşfedin." --- <SDKv4> Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüze nelerin dahil edileceğini ve nasıl görüneceğini siz belirlersiniz. Adapty, remote configuration'ı almanız için bir yöntem sunar; özel paywall'ınızı nasıl göstereceğiniz tamamen size kalmıştır. ## Flow remote config'ini alın ve sunun \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` listesinde yapılandırılmış her locale için bir `AdaptyRemoteConfig` girişi taşır. Kullanıcının tercihine uyan locale'i seçin, ardından ihtiyacınız olan değerleri okuyun. ```kotlin showLineNumbers Adapty.getFlow("YOUR_PLACEMENT_ID") .onSuccess { flow -> val config = flow.remoteConfigs.firstOrNull { it.locale == "en" } ?: flow.remoteConfigs.firstOrNull() val headerText = config?.dataMap?.get("header_text") as? String // use the remote config values } .onError { error -> // handle the error } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada işleme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından, çeşitli cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunduğundan emin olun. :::warning Adapty analytics'in funnel'lar ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı şekilde [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-kmp#track-paywall-view-events) emin olun. ::: Paywallı görüntüledikten sonra satın alma flow'unu ayarlamaya devam edin. Kullanıcı bir satın alma işlemi yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında daha fazla bilgi için [Satın alma yapma](kmp-making-purchases) sayfasını okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](kmp-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilerek bu durumlarda bile sorunsuz bir deneyim sağlar. ## Flow görüntüleme olaylarını takip edin \{#track-paywall-view-events\} Adapty, flow'larınızın ve paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da, görüntüleme olaylarını kaydetmek için sizin müdahaleniz gereklidir; çünkü bir kullanıcının flow'u ne zaman gördüğünü yalnızca siz bilebilirsiniz. Görüntüleme olayı kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterlidir; bu, huniler ve A/B testlerindeki metriklerinize yansıyacaktır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow veya paywall'ları görüntülüyorsanız `.logShowFlow(flow)` çağrısı yapmanıza gerek yoktur. Bu durumlarda Adapty görüntülemeleri otomatik olarak takip eder. ::: ```kotlin showLineNumbers Adapty.logShowFlow(flow) .onSuccess { // flow view logged successfully } .onError { error -> // handle the error } ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :-------- | :------- |:-----------------------------------------------------------------| | **flow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | </SDKv4> <SDKv3> Remote config kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywallınızın içeriği ve görünümü tamamen size kalmıştır. Remote config aracılığıyla yapılandırılan özel paywallınızı göstermek için remote config'i çekmeye yarayan bir metot sunuyoruz. ## Paywall remote config'ini alma ve gösterme \{#get-paywall-remote-config-and-present-it\} Bir paywall'ın remote config'ini almak için `remoteConfig` özelliğine erişin ve ihtiyacınız olan değerleri çıkarın. ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String // use the remote config values }.onError { error -> // handle the error } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından, farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunduğundan emin olun. :::warning Adapty analitiğinin dönüşüm hunileri ve A/B testleri için bilgi toplayabilmesi amacıyla aşağıda açıklandığı şekilde [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-kmp#track-paywall-view-events-1) emin olun. ::: Paywall'ı gösterdikten sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, paywall'ınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](kmp-making-purchases) bölümüne bakın. [Yedek paywall olarak bir fallback paywall oluşturmanızı](kmp-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellekte veri bulunmadığında kullanıcılara gösterilecek ve her koşulda sorunsuz bir deneyim sağlayacaktır. ## Paywall görüntüleme olaylarını kaydetme \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da paywall görüntülemelerini kaydetmek için sizin müdahaleniz gerekir; çünkü bir kullanıcının paywall'ı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırın; bu, huni ve A/B testi metriklerinize yansıyacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywall'ları gösteriyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall = paywall) .onSuccess { // paywall view logged successfully } .onError { error -> // handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:----------------------------------------------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/) nesnesi. | </SDKv3> --- # File: kmp-making-purchases --- --- title: "Kotlin Multiplatform SDK ile mobil uygulamada satın alma yapma" description: "Adapty ile uygulama içi satın alma ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall'lar göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, satın almaları desteklemek için yalnızca bu paywall'ları göstermek yeterlidir. Paywall Builder kullanmıyorsanız, satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için ayrı bir `.makePurchase()` metodu kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime girerek işlemlerini tamamlamasını sağlar. Kullanıcının satın almaya çalıştığı ürün için paywall'da aktif bir promosyon teklifi varsa, Adapty bunu satın alma anında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın. Diğer durumlarda, [iOS'ta kullanıcının başlangıç teklifi için uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlarsanız uygulamanız yayın sırasında reddedilebilir. Üstelik başlangıç teklifine hak kazanan kullanıcılara tam fiyat uygulanmasına yol açabilir. ::: [Başlangıç yapılandırmasını](quickstart) tek bir adım atlamadan tamamladığınızdan emin olun. Aksi takdirde satın almaları doğrulayamayız. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik işlenir — bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](kmp-implement-paywalls-manually) bakın. ::: ```kotlin showLineNumbers Adapty.makePurchase(product = product).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } }.onError { error -> // Handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:--------------------------------------------------------------------------------------------------------------------------------------------------| | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.</p><p>Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.</p> | :::warning **Not:** Hâlâ Apple'ın StoreKit v2.0'ın altındaki bir sürümünü ve Adapty SDK v2.9.0'ın altındaki bir sürümünü kullanıyorsanız, bunun yerine [Apple App Store paylaşılan sırrını](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem Apple tarafından kullanımdan kaldırılmıştır. ::: ## Satın alma sırasında abonelik değiştirme \{#change-subscription-when-making-a-purchase\} Kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu sürecin işleyişi uygulama mağazasına göre değişir. Google Play'de abonelik otomatik olarak güncellenmez. Aşağıda açıklandığı gibi geçişi mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka biriyle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```kotlin showLineNumbers val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( oldSubVendorProductId = "old_subscription_product_id", replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE ) val purchaseParams = AdaptyPurchaseParameters.Builder() .setSubscriptionUpdateParams(subscriptionUpdateParams) .build() Adapty.makePurchase( product = product, parameters = purchaseParams ).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } }.onError { error -> // Handle the error } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | |:---------------|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **parameters** | isteğe bağlı | [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) aracılığıyla iletilen bir [`AdaptyAndroidSubscriptionUpdateParameters`](https://kmp.adapty.io/////adapty/com.adapty.kmp.models/-adapty-android-subscription-update-parameters/) nesnesi. | Abonelikler ve değiştirme modları hakkında daha fazla bilgi için Google Geliştirici belgelerine bakabilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değiştirme modları önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()) değiştirme modu. Not: Bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme desteklenmez. - [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()) değiştirme modu. Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik fatura dönemi sona erdiğinde gerçekleşir. ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanma sayfasını görüntülemek için: ```kotlin showLineNumbers Adapty.presentCodeRedemptionSheet() .onSuccess { // code redemption sheet presented successfully } .onError { error -> // handle the error } ``` :::danger Gözlemlerimize göre bazı uygulamalarda Teklif Kodu Kullanma sayfası güvenilir çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için aşağıdaki formatta bir URL açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin birkaç aylık yenilenemez abonelik), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withGoogleEnablePendingPrepaidPlans(true) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } ``` --- # File: kmp-restore-purchase --- --- title: "Kotlin Multiplatform SDK'da Mobil Uygulamada Satın Almaları Geri Yükleme" description: "Sorunsuz bir kullanıcı deneyimi için Adapty'de satın almaları nasıl geri yükleyeceğinizi öğrenin." --- Satın Almaları Geri Yükleme, kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödenmeksizin erişmesini sağlayan bir özelliktir. Bu özellik özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywalllar'da satın almalar, sizin tarafınızdan ek bir kod gerektirmeksizin otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz. ::: Paywallı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almayı geri yüklemek için `.restorePurchases()` metodunu çağırın: ```kotlin showLineNumbers Adapty.restorePurchases().onSuccess { profile -> if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } }.onError { error -> // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>Bir [`AdaptyProfile`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-profile/) nesnesi. Bu model; access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir.</p><p>Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.</p> | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: implement-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDK'da Observer modunu uygulama" description: "Kotlin Multiplatform SDK'da kullanıcı abonelik etkinliklerini izlemek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve henüz tamamen Adapty'ye geçmeye hazır değilseniz, [Observer mode](observer-vs-full-mode)'u inceleyebilirsiniz. Temel haliyle Observer Mode; gelişmiş analitik ve attribution ile analitik sistemleriyle sorunsuz entegrasyon sunar. Bu sizin için yeterliyse yalnızca şunları yapmanız yeterli: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak Observer Mode'u etkinleştirin. Kurulum talimatlarını [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) için takip edin. 2. Mevcut satın alma altyapınızdan [işlemleri Adapty'ye bildirin](report-transactions-observer-mode-kmp). :::tip SDK v4'te, Observer modunda Adapty tarafından render edilen flow'ları ve paywall'ları da sunabilirsiniz: kullanıcı satın alma veya geri yükleme düğmesine dokunduğunda, SDK eylemi kodunuza devreder, böylece satın alma veya geri yükleme işlemini kendiniz gerçekleştirebilirsiniz. Bkz. [Observer modunda flow'ları sunma](kmp-present-flows-in-observer-mode). ::: ## Observer mode kurulumu \{#observer-mode-setup\} Satın almaları ve abonelik durumunu kendiniz yönetip Adapty'yi yalnızca abonelik etkinlikleri ve analitik için kullanıyorsanız Observer Mode'u etkinleştirin. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle işlemleri kendiniz yönettiğinizden emin olun. ::: ```kotlin showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withObserverMode(true) // default false .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised in observer mode") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer mode](observer-vs-full-mode)'u kontrol eden bir boolean değer. Varsayılan değer `false`'tur. | ## Observer Mode'da Adapty paywalllarını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywalllarını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer modunda biraz ek kurulum gerektirir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir: 1. [Remote config paywallları](present-remote-config-paywalls-kmp) için paywallları her zamanki gibi gösterin. 3. Satın alma işlemleriyle [paywallları ilişkilendirin](report-transactions-observer-mode-kmp). --- # File: report-transactions-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDK'da Observer Mode'da İşlemleri Raporlama" description: "Kotlin Multiplatform SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'unda satın alma işlemlerini raporlayın." --- Observer Mode'da Adapty SDK, mevcut satın alma sisteminiz aracılığıyla gerçekleştirilen satın almaları kendi başına takip edemez. App Store'dan gelen işlemleri kendiniz raporlamanız gerekir. Analizlerde hata oluşmaması için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız kritik öneme sahiptir. Her işlemi Adapty'nin tanıması için `reportTransaction` kullanarak açıkça raporlayın. :::warning **İşlem raporlamayı atlama!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, analitiklerde görünmez ve entegrasyonlara iletilmez. ::: Adapty paywallları kullanıyorsanız işlemi raporlarken `variationId` ekleyin. Bu, satın almayı tetikleyen paywalla bağlayarak paywall analizlerinin doğru çalışmasını sağlar. ```kotlin showLineNumbers Adapty.reportTransaction( transactionId = "your_transaction_id", variationId = paywall.variationId ).onSuccess { profile -> // Transaction reported successfully // profile contains updated user data }.onError { error -> // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | --------------- | -------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | zorunlu | App Store satın almasından gelen işlem kimliği. Genellikle mağaza tarafından döndürülen satın alma token'ı veya işlem tanımlayıcısıdır. | | variationId | isteğe bağlı | Varyantın string tanımlayıcısı. [AdaptyPaywall](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/) nesnesinin `variationId` özelliği kullanılarak alınabilir. | --- # File: kmp-troubleshoot-purchases --- --- title: "Kotlin Multiplatform SDK'da satın alma sorunlarını giderme" description: "Kotlin Multiplatform SDK'da satın alma sorunlarını giderme" --- Bu rehber, Kotlin Multiplatform SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrıldı ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu durum genellikle eksik Google Play Store kurulumuna ya da yapılandırma sorunlarına işaret eder. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## makePurchase iki kez çağrılıyor \{#makepurchase-is-invoked-twice\} **Sorun**: `makePurchase` metodu aynı satın alma için birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya hızlı kullanıcı etkileşimleri nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## Observer modunda AdaptyError.cantMakePayments \{#adaptyerror-cantmakepayments-in-observer-mode\} **Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modunda satın almaları Adapty'nin `makePurchase` metodu üzerinden değil, kendi tarafınızda yönetmeniz gerekir. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmalı ya da observer modunda satın almaları kendi tarafınızda yönetmelisiniz. Daha fazla bilgi için [Observer modunu uygulama](implement-observer-mode-kmp) konusuna bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan faturalandırma kullanılamıyor hatası alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın kullanılamadığını belirten bir Google Play Billing Library hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store dokümantasyonunda daha fazla bilgi edinebilirsiniz: [BillingResult yanıt kodlarını yönetme](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamadı \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor hatası alıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturup tekrar deneyin. Bu, sandbox ile ilgili satın alma tamamlama handler sorunlarını çoğunlukla çözer. --- # File: kmp-user --- --- title: "Kotlin Multiplatform SDK'da Kullanıcılar ve Erişim" description: "Adapty SDK ile Kotlin Multiplatform uygulamanızda kullanıcılar ve access level'larla nasıl çalışacağınızı öğrenin." --- Bu sayfa, Kotlin Multiplatform uygulamanızda kullanıcılar ve access level'larla çalışmaya yönelik tüm kılavuzları içerir. İhtiyacınız olan konuyu seçin: - **[Kullanıcıları tanımlama](kmp-identifying-users)** - Uygulamanızdaki kullanıcıları nasıl tanımlayacağınızı öğrenin - **[Kullanıcı verilerini güncelleme](kmp-setting-user-attributes)** - Kullanıcı niteliklerini ve profil verilerini ayarlayın - **[Abonelik durumu değişikliklerini dinleme](kmp-listen-subscription-changes)** - Abonelik değişikliklerini gerçek zamanlı olarak takip edin - **[Çocuk Modu](kids-mode-kmp)** - Uygulamanız için Çocuk Modunu uygulayın --- # File: kmp-identifying-users --- --- title: "Kotlin Multiplatform SDK'da kullanıcıları tanımlama" description: "Kişiselleştirilmiş abonelik deneyimlerini iyileştirmek için Adapty'de kullanıcıları tanımlayın." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamanız gerekir. Kullanıcıları Customer User ID'lerine göre [Profiller](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz. ### Yapılandırma sırasında customer user ID ayarlama \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, `.activate()` metoduna `customerUserId` parametresi olarak geçirin: ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("YOUR_USER_ID") .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } } ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Yapılandırma sonrasında customer user ID ayarlama \{#setting-customer-user-id-after-configuration\} SDK yapılandırması sırasında kullanıcı ID'niz yoksa, `.identify()` metoduyla istediğiniz zaman sonradan ayarlayabilirsiniz. Bu metodun en yaygın kullanım senaryoları; kayıt veya giriş işleminin ardından, yani kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçişi sırasındadır. ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID").onSuccess { // successful identify }.onError { error -> // handle the error } ``` İstek parametreleri: - **Customer User ID** (zorunlu): kullanıcının string kimliği. :::warning Önemli kullanıcı verilerini yeniden gönderme Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty sunucularında o kullanıcıya ait bilgiler zaten bulunuyor olabilir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmak için otomatik olarak geçiş yapar. Anonim kullanıcıya özel nitelikler veya üçüncü taraf ağlardan attribution gibi veriler iletmişseniz, bu verileri tanımlanmış kullanıcı için yeniden göndermeniz gerekir. Ayrıca, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden istemeniz önemlidir; yeni kullanıcının verileri farklı olabilir. ::: ### Çıkış ve giriş yapma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak istediğiniz zaman kullanıcının oturumunu kapatabilirsiniz: ```kotlin showLineNumbers Adapty.logout().onSuccess { // successful logout }.onError { error -> // handle the error } ``` Ardından `.identify()` metoduyla kullanıcıyı tekrar giriş yaptırabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`iosAppAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini kendi kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle ilişkilendirir, böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulan sabit bir UUID kullanın ve aynı hesap için farklı cihazlarda aynı değeri tekrar kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş olur. Token'ı iki şekilde ayarlayabilirsiniz: SDK aktivasyonu sırasında veya kullanıcıyı tanımlarken. :::important `iosAppAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmelisiniz. Yalnızca token'ı geçerseniz, işleme dahil edilmez. ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## Gizlenmiş hesap ID'leri ayarlama (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak için belirli kullanım senaryolarında gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in kullanıcı bilgilerini anonim tutarken satın almaları tanımlamasına yardımcı olur; özellikle sahtekarlık önleme ve analitik açısından önemlidir. Uygulamanız hassas kullanıcı verileri işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri ayarlamanız gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın almaları takip etmesine olanak tanır. :::important `androidObfuscatedAccountId`'yi her zaman `customerUserId` ile birlikte geçirmelisiniz. Yalnızca gizlenmiş hesap ID'sini geçerseniz, işleme dahil edilmez. ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## Cihazlar arası kullanıcı tespiti \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: kmp-setting-user-attributes --- --- title: "Kotlin Multiplatform SDK'da kullanıcı özelliklerini ayarlama" description: "Adapty'de daha iyi kitle segmentasyonu için kullanıcı özelliklerini nasıl ayarlayacağınızı öğrenin." --- Uygulamanızın kullanıcısına e-posta, telefon numarası gibi isteğe bağlı özellikler ekleyebilirsiniz. Bu özellikleri kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz. ### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\} Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.FEMALE) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) .onSuccess { // profile updated successfully } .onError { error -> // handle the error } ``` `updateProfile` metoduyla daha önce ayarladığınız özelliklerin sıfırlanmayacağını unutmayın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen anahtarlar `<Key>` ve değerler `<Value>` aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum; izin verilen değerler: `AdaptyProfile.Gender.FEMALE`, `AdaptyProfile.Gender.MALE`, `AdaptyProfile.Gender.OTHER` | | birthday | Date | ### Özel kullanıcı özellikleri \{#custom-user-attributes\} Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin, fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi düzeyi gibi. Bu özellikleri segmentlerde kullanarak hedefli paywall'lar ve teklifler oluşturabilir, analitik aracılığıyla hangi ürün metriklerinin gelire en çok etki ettiğini de keşfedebilirsiniz. ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withCustomAttribute("key1", "value1") ``` Mevcut bir anahtarı silmek için `.withRemovedCustomAttribute()` metodunu kullanın: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withRemovedCustomAttribute("key2") ``` Bazen daha önce hangi özel özelliklerin eklendiğini öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın. Kullanıcı özellikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, sunucudaki özellikler son senkronizasyondan bu yana değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel özellik - Anahtar adları en fazla 30 karakter olabilir. Anahtar adında alfanümerik karakterler ve şu simgeler kullanılabilir: `_` `-` `.` - Değer, en fazla 50 karakterlik bir string veya float olabilir. --- # File: kmp-listen-subscription-changes --- --- title: "Kotlin Multiplatform SDK'da abonelik durumunu kontrol etme" description: "Kotlin Multiplatform uygulamanızda müşteri tutundurma oranını artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek oldukça kolaydır. Ürün ID'lerini kodunuza elle eklemenize gerek yok; bunun yerine aktif bir [access level](access-level) kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. Abonelik durumunu kontrol etmeye başlamadan önce [Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN)](enable-real-time-developer-notifications-rtdn) ayarlayın. ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) nesnesinin özellikleridir. Profili uygulamanız başladığında, örneğin [bir kullanıcıyı tanımladığınızda](android-identifying-users#setting-customer-user-id-on-configuration), almanızı ve değişiklik olduğunda güncellemenizi öneririz. Böylece profil nesnesini defalarca istek göndermeden kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için aşağıdaki [Abonelik durumu güncellemelerini dinleme](android-listen-subscription-changes) bölümünde anlatıldığı şekilde profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Sunucudan access level alma \{#retrieving-the-access-level-from-the-server\} Sunucudan access level almak için `.getProfile()` metodunu kullanın: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> // check the access }.onError { error -> // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profil | <p>Bir [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) nesnesi. Genellikle kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.</p><p></p><p>`.getProfile` metodu, her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (örneğin internet bağlantısı olmaması) Adapty SDK sunucudan bilgi alamazsa, önbellekteki veriler döndürülür. Adapty SDK'nın `AdaptyProfile` önbelleğini düzenli aralıklarla güncelleyerek bilgileri mümkün olduğunca güncel tuttuğunu da belirtmek gerekir.</p> | `.getProfile()` metodu, access level durumunu alabileceğiniz kullanıcı profilini sağlar. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin bir gazete uygulamanız varsa ve farklı konulara abonelik satıyorsanız "sports" ve "science" gibi access level'lar oluşturabilirsiniz. Ancak çoğu durumda yalnızca bir access level'a ihtiyaç duyarsınız; bu durumda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmeye yönelik bir örnek: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } }.onError { error -> // handle the error } ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir event tetikler. Adapty'den mesaj almak için birkaç ek yapılandırma yapmanız gerekir: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` Adapty, uygulama başlangıcında da bir event tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu kullanılamaz olsa bile önbellekteki veriler, profilin abonelik durumu hakkında bilgi vermek için kullanılabilir. Ancak önbellekten doğrudan veri isteği yapılamadığını belirtmek gerekir. SDK, profilin herhangi bir güncellemesini veya değişikliğini kontrol etmek için her dakika periyodik olarak sunucuyu sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler varsa, sunucuyla senkronize tutmak amacıyla önbellekteki verilere aktarılır. --- # File: kmp-deal-with-att --- --- title: "Kotlin Multiplatform SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumunu ve yönetimini kolaylaştırmak için Kotlin Multiplatform üzerinde Adapty'ye başlayın." --- Uygulamanız AppTrackingTransparency framework'ünü kullanıyor ve kullanıcıya uygulama izleme yetkilendirme isteği gösteriyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. ```kotlin showLineNumbers val profileParameters = AdaptyProfileParameters.Builder() .withAttStatus(3) // 3 = ATTrackingManagerAuthorizationStatusAuthorized .build() Adapty.updateProfile(profileParameters) .onSuccess { // ATT status updated successfully } .onError { error -> // handle AdaptyError } ``` :::warning Bu değeri değiştiği anda mümkün olduğunca erken göndermenizi önemle tavsiye ederiz; ancak bu şekilde veriler yapılandırdığınız entegrasyonlara zamanında iletilir. ::: --- # File: kids-mode-kmp --- --- title: "Kotlin Multiplatform SDK'da Çocuk Modu" description: "Google politikalarına uyum için Çocuk Modu'nu kolayca etkinleştirin. Kotlin Multiplatform SDK'da GAID veya reklam verisi toplanmaz." --- Kotlin Multiplatform uygulamanız çocuklara yönelikse [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız birkaç basit adımla bu politikaları karşılayacak ve uygulama mağazası incelemelerinden geçecek şekilde yapılandırabilirsiniz. ## Neler gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunların yanı sıra müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `<Ad.Soyad>` formatındaki kullanıcı kimliği, e-posta kullanımında olduğu gibi kesinlikle kişisel veri toplama olarak değerlendirilir. Çocuk Modu için en iyi uygulama; uyumu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (örneğin karma kimlikler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Çocuk Modu'nu Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde Güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamanın devre dışı bırakılması gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil Uygulama Kodunuzda Güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için Adapty SDK'yı başlatırken Android Advertising ID (AAID/GAID) ve IP adresi toplamanın devre dışı bırakılması gerekir: ```kotlin showLineNumbers override fun onCreate() { super.onCreate() val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") // highlight-start .withGoogleAdvertisingIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised with privacy settings") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } } ``` --- # File: kmp-onboardings --- --- title: "Kotlin Multiplatform SDK'da Onboardinglar" description: "Adapty SDK ile Kotlin Multiplatform uygulamanızda onboardinglarla nasıl çalışacağınızı öğrenin." --- :::warning **Onboardinglar SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık düzeltme veya iyileştirme almamaktadır. Bunun yerine [flow](kmp-get-pb-paywalls)'ları kullanın: onboardinglar WebView içinde çalışırken, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow & paywall'ları edinme](kmp-get-pb-paywalls) ve [Flow & paywall'ları görüntüleme](kmp-present-paywalls) konularına bakın. ::: <CustomDocCardList /> --- # File: kmp-get-onboardings --- --- title: "Kotlin Multiplatform SDK'da onboarding'leri alma" description: "Kotlin Multiplatform için Adapty'de onboarding'leri nasıl alacağınızı öğrenin." --- :::warning **Onboardings, SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow](kmp-get-pb-paywalls)'ları kullanın: onboarding'ler WebView içinde çalışırken, flow'lar cihazda doğrudan native olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall'ları edinme](kmp-get-pb-paywalls) ve [Flow ve paywall'ları görüntüleme](kmp-present-paywalls) konularına bakın. ::: Adapty Kontrol Paneli'nde builder ile [onboarding'in görsel kısmını tasarladıktan](design-onboarding) sonra, onu Kotlin Multiplatform uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır. Başlamadan önce şunları sağlayın: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) sürüm 3.15.0 veya daha yüksek bir sürümü yüklemiş olun. 2. [Bir onboarding oluşturmuş](create-onboarding) olun. 3. Onboarding'i bir [placement](placements)'a eklemiş olun. ## Onboarding'i getir \{#fetch-onboarding\} Kodsuz oluşturucumuzla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirip göstermesi gereken bir konfigürasyon içeren container olarak saklanır. Container tüm deneyimi yönetir; hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (sınav yanıtları veya form girişleri gibi) nasıl işleneceğini belirler. Container aynı zamanda analitik olaylarını otomatik olarak izler, bu yüzden ayrıca görüntüleme takibi uygulamanıza gerek yoktur. En iyi performans için, görsellerin kullanıcılara gösterilmeden önce indirilmesine yetecek kadar zaman tanımak amacıyla onboarding konfigürasyonunu erken getirin. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```kotlin showLineNumbers Adapty.getOnboarding( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` Parametreler: | Parametre | Varlık | Açıklama | |---------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements) tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenir. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.<p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınan veriyi döner. Kullanıcılarınızın her zaman en güncel veriye erişmesini sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar her zaman en güncel veriye ulaşamayabilir; ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, dolayısıyla oturum sırasında ağ isteklerini azaltmak için güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN, CDN'e erişilemediğinde ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı garanti edecek şekilde tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınan veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | ## Yanıt parametreleri \{#response-parameters\} | Parametre | Açıklama | |:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özelliklerle birlikte bir [`AdaptyOnboarding`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-onboarding/) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding getirme işlemini hızlandırın \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir onboarding'in getirilmesi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir onboarding görüntülemek isteyebilirsiniz. Bunu ele almak için, belirtilen placement'ın **All Users** kitlesi için onboarding'ini getiren `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Getir](#fetch-onboarding) bölümünde açıklandığı gibi `getOnboarding` metoduyla onboarding'i getirmek olduğunu anlamak kritik önem taşımaktadır. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı tercih edin; zira ikincisinin önemli kısıtlamaları bulunmaktadır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlara yol açabilir; ya geriye dönük uyumlu tasarımlar gerektirir ya da eski sürümlerin hatalı görüntülenebileceğini kabul etmeniz gerekir. - **Kişiselleştirme yok**: Yalnızca "Tüm Kullanıcılar" kitlesine yönelik içerik gösterir; ülke, attribution veya özel özelliklere dayalı hedefleme devre dışı kalır. Daha hızlı veri çekme bu dezavantajlara değiyorsa, aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın. ::: ```kotlin showLineNumbers Adapty.getOnboardingForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // istenen paywall }.onError { error -> // hatayı işle } ``` Parametreler: | Parametre | Varlık | Açıklama | |---------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.<br/>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, mevcut olması durumunda önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu senaryoda kullanıcılar en güncel verilere her zaman ulaşamayabilir, ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında olduğu gibi kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı çekmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının kısıtlı olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | --- # File: kmp-present-onboardings --- --- title: "Kotlin Multiplatform SDK'da onboarding'leri sunma" description: "Daha fazla dönüşüm sağlamak için onboarding'leri etkili biçimde nasıl sunacağınızı öğrenin." --- :::warning **Onboardinglar SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almamaktadır. Bunun yerine [flow'ları](kmp-get-pb-paywalls) kullanın: WebView içinde çalışan onboardingların aksine, flow'lar cihazda native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir native görünüm, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywallları alma](kmp-get-pb-paywalls) ve [Flow'ları ve paywallları gösterme](kmp-present-paywalls) konularına bakın. ::: Builder ile bir onboarding oluşturduysanız, Kotlin Multiplatform uygulamanızda onu kullanıcıya göstermek için ekstra kod yazmanıza gerek yok. Böyle bir onboarding, hem neyin gösterileceğini hem de nasıl gösterileceğini kendi içinde barındırır. Başlamadan önce şunları tamamladığınızdan emin olun: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.16.1 veya daha yeni bir sürümünü yüklemiş olun. 2. Bir [onboarding oluşturmuş](create-onboarding) olun. 3. Onboarding'i bir [placement](placements)'a eklemiş olun. Adapty Kotlin Multiplatform SDK, onboarding'leri sunmak için iki yöntem sağlar: - **Compose Multiplatform ile** - **Compose Multiplatform olmadan** ## Compose Multiplatform ile \{#with-compose-multiplatform\} Bir onboarding göstermek için `createOnboardingView` metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Onboarding'i tekrar göstermeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createOnboardingView` metodunu bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak hataya yol açabilir. ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createOnboardingView(onboarding = onboarding).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `AdaptyUIIOSPresentationStyle.FULLSCREEN` (varsayılan) veya `AdaptyUIIOSPresentationStyle.PAGESHEET` değerlerini kabul eder. ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createOnboardingView(onboarding = onboarding).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ### Onboarding'lerdeki linklerin nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\} Varsayılan olarak, onboarding'lerdeki linkler uygulama içi tarayıcıda açılır. Bu, web sayfalarını uygulamanızın içinde görüntüleyerek kullanıcıların uygulamalar arasında geçiş yapmadan içerikleri incelemesini sağlar ve kesintisiz bir kullanıcı deneyimi sunar. Linklerin harici tarayıcıda açılmasını tercih ederseniz, `externalUrlsPresentation` parametresini `AdaptyWebPresentation.EXTERNAL_BROWSER` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: ```kotlin showLineNumbers viewModelScope.launch { AdaptyUI.createOnboardingView( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.EXTERNAL_BROWSER // default – IN_APP_BROWSER ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ## Compose Multiplatform Olmadan \{#without-compose-multiplatform\} :::note `createNativeOnboardingView`, `io.adapty:adapty-kmp` çekirdek modülünün bir parçasıdır. Projeniz Compose Multiplatform kullanmıyorsa `io.adapty:adapty-kmp-ui` bağımlılığına ihtiyaç duymazsınız. ::: Compose Multiplatform olmadan bir onboarding eklemek için `createNativeOnboardingView` çağrısını yapın. Bu çağrı, layout'unuza eklediğiniz bir `AdaptyNativeOnboardingView` döndürür: <Tabs> <TabItem value="android" label="Android"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativeOnboardingView( context = context, viewModelStoreOwner = activity, onboarding = onboarding, observer = myOnboardingObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` </TabItem> <TabItem value="ios" label="iOS"> KMP arayüz varsayılan metotları Swift'te `@required` hale geldiğinden, `AdaptyUIOnboardingsEventsObserver`'ı doğrudan Swift üzerinden uygulayamazsınız. Önce `iosMain` içinde bir open base class tanımlayın: ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BaseOnboardingObserver : AdaptyUIOnboardingsEventsObserver ``` Ardından Swift'te yalnızca ihtiyacınız olanları geçersiz kılarak alt sınıf oluşturun: ```swift showLineNumbers title="Swift" class MyOnboardingObserver: BaseOnboardingObserver { override func onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // remove nativeView from your view hierarchy } } let nativeView = AdaptyUI.shared.createNativeOnboardingView( onboarding: onboarding, observer: MyOnboardingObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` </TabItem> </Tabs> ### View'u imha edin \{#dispose-the-view\} View'u layout'unuzdan kaldırırken `dispose()`'u çağırın. Bu işlem, olay dinleyicisinin kaydını siler ve dahili kaynakları serbest bırakır. ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` --- # File: kmp-handling-onboarding-events --- --- title: "Kotlin Multiplatform SDK'da onboarding olaylarını yönetin" description: "Adapty kullanarak Kotlin Multiplatform'da onboarding ile ilgili olayları yönetin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık hata düzeltmesi veya iyileştirme almıyorlar. Bunun yerine [flow'ları](kmp-get-pb-paywalls) kullanın: onboarding'lerin WebView içinde çalışmasının aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir yerel görünüm, daha hızlı yükleme süreleri ve WebView runtime bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall alma](kmp-get-pb-paywalls) ve [Flow ve paywall gösterme](kmp-present-paywalls) sayfalarına bakın. ::: Başlamadan önce şunları sağlayın: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.15.0 veya daha yeni bir sürümünü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. ## Onboarding olay gözlemcisini ayarlayın \{#set-up-the-onboarding-event-observer\} Onboarding olaylarını yönetmek için `AdaptyUIOnboardingsEventsObserver` arayüzünü uygulamanız ve `AdaptyUI.setOnboardingsEventsObserver()` ile kurmanız gerekir. Bu, genellikle ana aktivitenizde veya uygulama başlatma aşamasında olmak üzere uygulamanızın yaşam döngüsünün erken bir noktasında yapılmalıdır. ```kotlin // In your app initialization AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ## Özel eylemler \{#custom-actions\} Oluşturucuda bir butona **custom** eylem ekleyip bir ID atayabilirsiniz. Ardından bu ID'yi kodunuzda kullanarak özel bir eylem olarak yönetebilirsiniz. <img src={require('./img/ios-events-1.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir butona dokunduğunda, `onCustomAction` delege metodu oluşturucudaki eylem ID'siyle tetiklenir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCustomAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { when (actionId) { "openPaywall" -> { // Display paywall from onboarding // You would typically fetch and present a new paywall here mainUiScope.launch { // Example: Get paywall by placement ID // val paywallResult = Adapty.getPaywall("your_placement_id") // paywallResult.onSuccess { paywall -> // val paywallViewResult = AdaptyUI.createPaywallView(paywall) // paywallViewResult.onSuccess { paywallView -> // paywallView.present() // } // } } } "allowNotifications" -> { // Handle notification permissions } else -> { // Handle other custom actions } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## Onboardingi kapatma \{#closing-onboarding\} Bir kullanıcı **Close** eylemi atanmış bir butona dokunduğunda onboarding kapalı sayılır. Kullanıcı onboardingi kapattığında ne olacağını yönetmeniz gerekir. Örneğin: :::important Kullanıcı onboardingi kapattığında ne olacağını yönetmeniz gerekir. Örneğin, onboardingin kendisini görüntülemeyi durdurmanız gerekir. ::: [`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform) kullanıyorsanız `view.isStandaloneView` `false` olur — varsayılan uygulama `view.dismiss()` çağırmaz. Bu geri çağırımda görünümü düzeninizden kaldırın ve üzerinde `dispose()` çağırın. ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Dismiss the onboarding screen mainUiScope.launch { view.dismiss() } // Additional cleanup or navigation logic can be added here // For example, navigate back or show main app content } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## Paywall açma \{#opening-a-paywall\} :::tip Onboarding içinde paywall açmak istiyorsanız bu eventi işleyin. Paywall kapandıktan sonra açmak istiyorsanız daha doğrudan bir yol var: [`onboardingViewOnCloseAction`](#closing-onboarding) olayını işleyin ve event verisine güvenmeden paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, action ID'yi paywall placement ID'siyle eşit yapmaktır. Bu sayede placement ID'yi kullanarak paywall'ı anında alıp açabilirsiniz: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnPaywallAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Get the paywall using the placement ID from the action mainUiScope.launch { val paywallResult = Adapty.getPaywall(placementId = actionId) paywallResult.onSuccess { paywall -> val paywallViewResult = AdaptyUI.createPaywallView(paywall) paywallViewResult.onSuccess { paywallView -> paywallView.present() }.onError { error -> // handle the error } }.onError { error -> // handle the error } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## Onboarding yüklemesinin tamamlanması \{#finishing-loading-onboarding\} Bir onboarding yüklemeyi tamamladığında bu metod çağrılır: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewDidFinishLoading( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta ) { // Handle loading completion // You can add any initialization logic here } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## Gezinme olayları \{#navigation-events\} `onboardingViewOnAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır. `event` nesnesi şu türlerden biri olabilir: |Tür | Açıklama | |------------|-------------| | `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | Onboarding yüklendiğinde | | `AdaptyOnboardingsAnalyticsEventScreenPresented` | Herhangi bir ekran gösterildiğinde | | `AdaptyOnboardingsAnalyticsEventScreenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcının yanıtı) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | İkinci ekran gösterildiğinde | | `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | Kullanıcının e-posta adresi giriş alanı aracılığıyla toplandığında tetiklenir | | `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa son ekrana `final` ID'sini atayın. | | `AdaptyOnboardingsAnalyticsEventUnknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veriler) içerir | Her olay şu bilgileri içeren `meta` verisini barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Mevcut ekranın akıştaki konumu | | `screensTotal` | Akıştaki toplam ekran sayısı | Analitik olaylarını takip için nasıl kullanabileceğinize dair bir örnek: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnAnalyticsEvent( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, event: AdaptyOnboardingsAnalyticsEvent ) { when (event) { is AdaptyOnboardingsAnalyticsEventOnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingsAnalyticsEventOnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingsAnalyticsEventUnknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } private fun trackEvent(eventName: String, meta: AdaptyUIOnboardingMeta, elementId: String? = null, reply: String? = null) { // Implement your analytics tracking here // For example, send to your analytics service } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // OnboardingStarted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "welcome_screen", "screenIndex": 0, "screensTotal": 4 } } // ScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 4 } } // ScreenCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 }, "elementId": "profile_form", "reply": "success" } // SecondScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // UserEmailCollected { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // OnboardingCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "final_screen", "screenIndex": 3, "screensTotal": 4 } } ``` </Details> --- # File: kmp-onboarding-input --- --- title: "Kotlin Multiplatform SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Kotlin Multiplatform uygulamanızda onboarding verilerini kaydedin ve kullanın." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırılmıştır ve gelecekteki bir sürümde kaldırılacaktır.** Artık düzeltme veya iyileştirme almamaktadır. Bunun yerine [flow'ları](kmp-get-pb-paywalls) kullanın: onboarding'lerin aksine, WebView içinde çalışan onboarding'lerin yerine flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı olmaksızın kullanım sunar. Başlamak için [Flow'ları ve paywall'ları edinin](kmp-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleyin](kmp-present-paywalls) sayfalarına bakın. ::: Kullanıcılarınız bir quiz sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `onboardingViewOnStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsSelectParams -> { // Handle single selection val id = params.id val value = params.value val label = params.label AppLogger.d("Selected option: $label (id: $id, value: $value)") } is AdaptyOnboardingsMultiSelectParams -> { // Handle multiple selections } is AdaptyOnboardingsInputParams -> { // Handle text input } is AdaptyOnboardingsDatePickerParams -> { // Handle date selection } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>Kaydedilen veri örnekleri (format uygulamanıza göre farklılık gösterebilir)</summary> ```javascript // Example of a saved select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "preferences_screen", "screen_index": 1, "total_screens": 3 }, "action": { "element_id": "preference_selector", "element_type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 3 }, "action": { "element_id": "interests_selector", "element_type": "multi_select", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "name_input", "element_type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "birthday_picker", "element_type": "date_picker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini veriyle zenginleştir \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle anında ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak için, eylemi işlerken girdi verisiyle [kullanıcı profilini güncellemeniz](kmp-setting-user-attributes) gerekir. Örneğin, kullanıcılardan `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak ayarlamak istiyorsunuz. Ayrıca `email` alanına e-postalarını girmelerini istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsInputParams -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (elementId) { "name" -> { when (val input = params.input) { is AdaptyOnboardingsTextInput -> { builder.withFirstName(input.value) } } } "email" -> { when (val input = params.input) { is AdaptyOnboardingsEmailInput -> { builder.withEmail(input.value) } } } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Profile updated: ${profile.email}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ### Yanıtlara göre paywallları özelleştir \{#customize-paywalls-based-on-answers\} Onboardinglardaki sınavları kullanarak, kullanıcıların onboardingı tamamladıktan sonra göreceği paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara spor deneyimleri hakkında soru sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding oluşturucusuna [bir sınav ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın. 2. Sınav yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel özellikler belirleyin](kmp-setting-user-attributes). ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Handle quiz responses and set custom attributes when (params) { is AdaptyOnboardingsSelectParams -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.value) } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Custom attribute 'experience' set to: ${params.value}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` 3. Her özel özellik değeri için [segmentler oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitleleri](audience) ekleyin. 5. Uygulama kodunuzda placement için [bir paywall gösterin](kmp-paywalls). Onboardinginizde paywall açan bir düğme varsa, paywall kodunu [bu düğmenin eylemine yanıt olarak](kmp-handling-onboarding-events#opening-a-paywall) uygulayın. --- # File: kmp-best-practices --- --- title: "Kotlin Multiplatform SDK'da en iyi uygulamalar" description: "Kotlin Multiplatform'da Adapty SDK entegrasyonu için referans desenler — çağrı sırası, hata yönetimi ve diğer production hazırlığı kuralları." --- <CustomDocCardList /> --- # File: kmp-sdk-call-order --- --- title: "Kotlin Multiplatform SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak premium erişim kaybını, eksik attribution'ı ve aralıklı aktivasyon hatalarını önleyin." --- `Adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağıramazsınız. Tamamlanana kadar SDK'nın herhangi bir durumu yoktur. `activate()` ile eş zamanlı ya da öncesinde yapılan her çağrı aktivasyon hatasıyla sonuçlanır. Bkz. [Kotlin Multiplatform SDK'da hataları yönetme](kmp-handle-errors). Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir customer user ID topluyorsanız, o noktada `Adapty.identify()` çağırın. `identify` tamamlanana kadar kullanıcı eylemi gerektiren metotları çağırmayın. Bu metotlarla yarışan çağrılar ya hata döndürür ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP ID'leri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'lar (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `Adapty.activate` çağrısından önce bunları başlatın ve UID callback'lerini bekleyin. Aksi takdirde MMP ID'si kısa ömürlü anonim bir profile düşer ve tanımlanmış profile her zaman aktarılamaz. AppsFlyer'a özgü detaylar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıra \{#the-correct-order\} Takip edeceğiniz yol iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analytics SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. Önce SDK'yı etkinleştirin, ardından SDK metodlarını çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analytics SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama açılışında müşteri kullanıcı kimliğiniz varsa, `activate()` çağrısından önce `AdaptyConfig.Builder`'a aktarın (adım 2a). Bu yol hiçbir zaman anonim bir profil oluşturmaz, dolayısıyla adım 4 gereksizdir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlangıcında, ilk olarak | MMP'nin UID geri çağrısını bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | Uygulama başlangıcında, 1. adımdan sonra, customer user ID'niz varsa | Önerilen. Anonim profil oluşturulmaz. | | 2b | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").build())` `withCustomerUserId` olmadan | Uygulama başlangıcında, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` | 2. adımdan sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için gereklidir. | | 4 | `Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulamayla 2b yolunda | Herhangi bir kullanıcı işlemi çağrısından önce `onSuccess` bekleyin. `identify` sırasında yapılan eş zamanlı çağrılar anonim profile düşebilir. | | 5 | `getPaywall` (SDK v4'te `getFlow`), `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi hâlde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::important Bu adımların atlanması, geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitle için döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar bir web checkout'u (Stripe, Paddle) üzerinden satın alım yapıp daha sonra native uygulamayı yüklerse, cihazdaki ilk `activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Customer user ID'yi uygulama başlatılmadan önce (auth akışından veya install referrer'dan) çözümleyebiliyorsanız, doğrudan `AdaptyConfig.Builder`'a aktarın. Aksi takdirde, `identify("YOUR_USER_ID")` ve ardından `restorePurchases` çağrısını yapana kadar web satın alımı cihazda görünmez. Her web checkout'uyla birlikte gönderilecek metadata için bakınız: - [Stripe](stripe) - [Paddle](paddle) --- # File: kmp-optimize-paywall-fetching --- --- title: "Kotlin Multiplatform SDK'da paywall getirmeyi optimize etme" description: "Adapty paywalllerini güvenilir şekilde getirin: Kotlin Multiplatform için zamanlama, önbellekleme ve yedek desenler." --- Kotlin Multiplatform'da güvenilir bir paywall getirme işlemi üç şeyi yapar: hızlı render eder, kitleye göre hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz biçimde yedek seçeneğe geçer. Aşağıdaki kurallar bunları sağlamak için zamanlama, önbellekleme ve yedek desenlerini kapsar. :::tip `Adapty.activate()` ve `Adapty.identify()` çağrılarının tamamlandığı varsayılmaktadır. Bkz. [Kotlin Multiplatform SDK'da çağrı sırası](kmp-sdk-call-order). ::: Aşağıdaki tavsiyeler v3 metod adlarını kullanmaktadır. SDK v4'te `getPaywall`, `getFlow` olarak yeniden adlandırılmıştır ([migration kılavuzuna](migration-to-kmp-sdk-v4) bakın) — tüm kurallar değişmeksizin geçerliliğini korur. ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Yapılacak | Yapılmayacak | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı getirin. | Başlatma sırasında tüm placement'ları eş zamanlı olarak önceden getirin. | Toplu önceden getirme, ana thread'i bloke eder ve bu sürede siyah ekran görünür. | | `getPaywall`'ı attribution çözümlendikten sonra çağırın — örneğin `activate`'ten 1–2 saniye sonra veya `setOnProfileUpdatedListener` tetiklendikten sonra. | `getPaywall`'ı uygulama başlangıcında çağırın. | Attribution henüz gelmemiştir. Paywall, varsayılan kitleye göre çözümlenir ve segment ile ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall`'ın sonucunu süresiz bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf kullanıcılar ağ çözümlenene kadar boş ekranla karşılaşır — ya da uygulamayı kapatır. | `fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall'ları ve ürünleri getirme](fetch-paywalls-and-products-kmp) sayfasına, doğru placement seçimi için ise [Placement'lar](placements) sayfasına bakın. ## Zayıf bağlantı için ayarlamalar \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantı yaşanan pazarlar (kırsal alanlar, toplu taşıma güzergahları, yönlendirme sorunları olan bölgeler) için: - Her fetch işleminde (ilk fetch hariç) `fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` kullanın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin. - Paywall gösterimini `Adapty.getProfile()` çağrısına bağlamayın. Yavaş bir profil yüklemesinin arayüzü bloke etmemesi için `getPaywall` çağrısını bağımsız olarak yapın. --- # File: kmp-test --- --- title: "Kotlin Multiplatform SDK'da Test ve Yayınlama" description: "Adapty ile Kotlin Multiplatform uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Adapty SDK'yı Kotlin Multiplatform uygulamanıza entegre ettiyseniz her şeyin doğru kurulduğunu ve satın almaların beklendiği gibi çalıştığını test etmek isteyeceksinizdir. Bu, hem SDK entegrasyonunu hem de sandbox ortamıyla gerçek satın alma akışını test etmeyi kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almalarınızı kapsamlı biçimde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayına hazırlanın \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesini](release-checklist) takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırıldı - Satın almalar tamamlanıyor ve Adapty'ye raporlanıyor - Erişim doğru biçimde açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılandı --- # File: kmp-reference --- --- title: "Kotlin Multiplatform SDK Referansı" description: "Adapty Kotlin Multiplatform SDK için referans belgeleri." --- Bu sayfa, Adapty Kotlin Multiplatform SDK için referans belgeleri içermektedir. İhtiyacınız olan konuyu seçin: - **[SDK modelleri](https://kmp.adapty.io/adapty/)** - SDK tarafından kullanılan veri modelleri ve yapıları - **[Hataları yönetme](kmp-handle-errors)** - Hata yönetimi ve sorun giderme --- # File: kmp-handle-errors --- --- title: "Kotlin Multiplatform SDK'da hataları işleme" description: "Kotlin Multiplatform uygulamanızda Adapty ile hataları nasıl işleyeceğinizi öğrenin." --- Bu sayfa, Adapty Kotlin Multiplatform SDK'sında hata işlemeyi ele almaktadır. ## Hata işlemenin temelleri \{#error-handling-basics\} Tüm Adapty SDK metotları, başarı veya hata olabilen sonuçlar döndürür. Her iki durumu da her zaman işleyin: <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Handle success } is AdaptyResult.Error -> { val error = result.error // Handle error Log.e("Adapty", "Error: ${error.message}") } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // Handle success } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle error Log.e("Adapty", "Error: " + error.getMessage()); } }); ``` </TabItem> </Tabs> ## Yaygın hata kodları \{#common-error-codes\} | Hata Kodu | Açıklama | Çözüm | |------------|-------------|----------| | 1000 | Ürün ID'si bulunamadı | Kontrol panelinde ürün yapılandırmasını kontrol edin | | 1001 | Ağ hatası | İnternet bağlantısını kontrol edin | | 1002 | Geçersiz SDK anahtarı | SDK anahtarınızı doğrulayın | | 1003 | Ödeme yapılamıyor | Cihaz ödemeleri desteklemiyor | | 1004 | Ürün mevcut değil | Ürün mağazada yapılandırılmamış | ## Belirli hataları işleme \{#handle-specific-errors\} ### Ağ hataları \{#network-errors\} <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.getPaywall("main") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1001 -> { // Network error - show offline message showOfflineMessage() } else -> { // Other errors showErrorMessage(error.message) } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.getPaywall("main", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1001: // Network error - show offline message showOfflineMessage(); break; default: // Other errors showErrorMessage(error.getMessage()); break; } } }); ``` </TabItem> </Tabs> ### Satın alma hataları \{#purchase-errors\} <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers product.makePurchase { result -> when (result) { is AdaptyResult.Success -> { val purchase = result.value // Purchase successful showSuccessMessage() } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1003 -> { // Can't make payments showPaymentNotAvailableMessage() } 1004 -> { // Product not available showProductNotAvailableMessage() } else -> { // Other purchase errors showPurchaseErrorMessage(error.message) } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers product.makePurchase(result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchase purchase = ((AdaptyResult.Success<AdaptyPurchase>) result).getValue(); // Purchase successful showSuccessMessage(); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1003: // Can't make payments showPaymentNotAvailableMessage(); break; case 1004: // Product not available showProductNotAvailableMessage(); break; default: // Other purchase errors showPurchaseErrorMessage(error.getMessage()); break; } } }); ``` </TabItem> </Tabs> ## Hata kurtarma stratejileri \{#error-recovery-strategies\} ### Ağ hatalarında yeniden deneme \{#retry-on-network-errors\} <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers fun getPaywallWithRetry(placementId: String, maxRetries: Int = 3) { var retryCount = 0 fun attemptGetPaywall() { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && retryCount < maxRetries) { // Network error - retry retryCount++ Handler(Looper.getMainLooper()).postDelayed({ attemptGetPaywall() }, 1000 * retryCount) // Exponential backoff } else { // Max retries reached or other error showErrorMessage(error.message) } } } } } attemptGetPaywall() } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers public void getPaywallWithRetry(String placementId, int maxRetries) { AtomicInteger retryCount = new AtomicInteger(0); Runnable attemptGetPaywall = new Runnable() { @Override public void run() { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && retryCount.get() < maxRetries) { // Network error - retry retryCount.incrementAndGet(); new Handler(Looper.getMainLooper()).postDelayed(this, 1000 * retryCount.get()); } else { // Max retries reached or other error showErrorMessage(error.getMessage()); } } }); } }; attemptGetPaywall.run(); } ``` </TabItem> </Tabs> ### Önbelleğe alınmış veriye geri dönme \{#fallback-to-cached-data\} <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers class PaywallManager { private var cachedPaywall: AdaptyPaywall? = null fun getPaywall(placementId: String) { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value cachedPaywall = paywall showPaywall(paywall) } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall!!) showOfflineIndicator() } else { // No cache available or other error showErrorMessage(error.message) } } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers public class PaywallManager { private AdaptyPaywall cachedPaywall; public void getPaywall(String placementId) { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); cachedPaywall = paywall; showPaywall(paywall); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall); showOfflineIndicator(); } else { // No cache available or other error showErrorMessage(error.getMessage()); } } }); } } ``` </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} - [Code-1000 noProductIDsFound hatası için düzeltme](InvalidProductIdentifiers-kmp) - [Code-1003 cantMakePayments hatası için düzeltme](cantMakePayments-kmp) - [Eksiksiz API referansı](https://android.adapty.io) - Tam SDK dokümantasyonu --- # File: InvalidProductIdentifiers-kmp --- --- title: "Kotlin Multiplatform SDK'da Code-1000 noProductIDsFound hatasının çözümü" description: "Adapty'de abonelik yönetirken geçersiz ürün tanımlayıcısı hatalarını giderin." --- 1000 kodlu `noProductIDsFound` hatası, paywall'da istediğiniz ürünlerin App Store'da listelenmiş olmasına rağmen satın alma için kullanılamadığını gösterir. Bu hata zaman zaman `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız görünüyorsa görmezden gelebilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız sorunu çözmek için şu adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin \{#step-3-check-products\} 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne geçin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. Ürünleriniz **Subscriptions** bölümünde listelenecektir. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. Değilse [App Store'daki Ürün](app-store-products) sayfasındaki talimatları izleyin. <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Tablodaki ürün ID'sini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesindekiyle karşılaştırın. ID'ler eşleşmiyorsa tablodan ürün ID'sini kopyalayın ve Adapty Kontrol Paneli'nde bu ID ile [bir ürün oluşturun](create-product). <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ürünleri görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** bölümüne inin ve gerekli tüm ülke ve bölgelerin listelendiğinden emin olun. <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'te **Monetization** → **Subscriptions** bölümüne gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** bölümüne inin ve **Current Pricing for New Subscribers** kısmını genişletin. <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Gerekli tüm fiyatların listelendiğinden emin olun. <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. Uygulamanın ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) ana sayfasında **Business** seçeneğine tıklayın. <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şirketinizin adını seçin. 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** bilgilerinin hepsinin **Active** olarak göründüğünü doğrulayın. <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayına alabilirsiniz. ## Adım 6. Ürün takılıysa yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5 arası adımların hepsi geçiyor olabilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — yine de SDK `1000 noProductIDsFound` hatası döndürüyor olabilir. Bu durumda ürün Apple'ın kayıt defterinde takılı kalmış olabilir. Apple'ın ürün kayıt defteri zaman zaman öyle bir duruma giriyor ki ürün App Store Connect'in arayüzünde görünüyor ama StoreKit arama yoluna açık olmuyor. Ürünü App Store Connect'te silip aynı ürün kimliğiyle yeniden oluşturun. Yayılmanın tamamlanması için yeniden oluşturmanın ardından 24 saate kadar bekleyin. --- # File: cantMakePayments-kmp --- --- title: "Kotlin Multiplatform SDK'da Code-1003 cantMakePayment Hatasının Çözümü" description: "Adapty'de abonelikleri yönetirken ödeme yapılamıyor hatasını giderin." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: kmp-sdk-migration-guides --- --- title: "Kotlin Multiplatform SDK Geçiş Kılavuzları" description: "Adapty Kotlin Multiplatform SDK sürümleri için geçiş kılavuzları." --- Bu sayfa, Adapty Kotlin Multiplatform SDK için tüm geçiş kılavuzlarını içermektedir. Ayrıntılı talimatlar için geçiş yapmak istediğiniz sürümü seçin: - **[v4.0'a (beta) geçiş](migration-to-kmp-sdk-v4)** - **[v3.15'e geçiş](migration-to-kmp-315)** --- # File: migration-to-kmp-sdk-v4 --- --- title: "Adapty Kotlin Multiplatform SDK'yı v. 4.0'a Geçirin" description: "Adapty Kotlin Multiplatform SDK v4.0 (beta) sürümüne geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty Kotlin Multiplatform SDK 4.0 (beta), flow'ları tanıtıyor ve paywall API'lerini buna göre yeniden adlandırıyor. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliğine gerek yoktur. ## Hızlı referans \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty.getPaywall(placementId, locale)` | `Adapty.getFlow(placementId)` | | `Adapty.getPaywallForDefaultAudience(placementId, locale)` | `Adapty.getFlowForDefaultAudience(placementId)` | | `Adapty.getPaywallProducts(paywall)` | `Adapty.getPaywallProducts(flow)` | | `Adapty.logShowPaywall(paywall)` | `Adapty.logShowFlow(flow)` | | `AdaptyPaywall` | `AdaptyFlow` | | `AdaptyUI.createPaywallView(paywall, ...)` | `AdaptyUI.createFlowView(flow, ...)` | | `AdaptyUI.createNativePaywallView(...)` → `AdaptyNativePaywallView` | `AdaptyUI.createNativeFlowView(...)` → `AdaptyNativeFlowView` | | `AdaptyUIPaywallView` | `AdaptyUIFlowView` | | `AdaptyUI.presentPaywallView(view)` / `dismissPaywallView(view)` | `AdaptyUI.presentFlowView(view)` / `dismissFlowView(view)` | | `AdaptyUI.setPaywallsEventsObserver(observer)` | `AdaptyUI.setFlowsEventsObserver(observer)` | | `AdaptyUI.registerPaywallEventsListener` / `unregisterPaywallEventsListener` | `AdaptyUI.registerFlowEventsListener` / `unregisterFlowEventsListener` | | `AdaptyUIPaywallsEventsObserver` | `AdaptyUIFlowsEventsObserver` | | `AdaptyUIPaywallPlatformView(paywall, ...)` | `AdaptyUIFlowPlatformView(flow, ...)` | | `paywallViewDidPerformAction`, `paywallViewDidAppear` ve diğer `paywallView...` callback'leri | `flowViewDidPerformAction`, `flowViewDidAppear` ve diğer `flowView...` callback'leri | | `paywallViewDidFailRendering` | `flowViewDidReceiveError` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` de adını korur, artık bir `AdaptyFlow` alır. `getFlow` ve `getFlowForDefaultAudience` metodları artık `locale` parametresi almaz. Satın alma ve profil API'leri (`makePurchase`, `restorePurchases`, `getProfile`, `identify`, `updateProfile`) ve `setFallback` aracılığıyla yedekler değişmeden kalmıştır. Onboarding metodları hâlâ çalışır ancak kullanımdan kaldırılmıştır — bkz. [Onboarding API kullanımdan kaldırma](#onboarding-api-deprecation). Bazı varsayılan davranışlar değişmiştir — bkz. [Varsayılan davranış değişiklikleri](#default-behavior-changes). ## Kurulum \{#installation\} v4.0 bir ön sürüm olduğundan, tam sürümü sabitleyin — Gradle dinamik aralıklarla ön sürümleri seçmez: ```toml showLineNumbers title="libs.versions.toml" [versions] adapty-kmp = "4.0.0-beta.1" [libraries] adapty-kmp = { module = "io.adapty:adapty-kmp", version.ref = "adapty-kmp" } adapty-kmp-ui = { module = "io.adapty:adapty-kmp-ui", version.ref = "adapty-kmp" } ``` `adapty-kmp-ui` modülü yalnızca flow'ları ve paywallları Compose Multiplatform katmanıyla (`view.present()`) render ediyorsanız gereklidir. Tam kurulum için [Adapty SDK'yı Yükle](sdk-installation-kotlin-multiplatform) sayfasına bakın. Altta yatan yerel Adapty SDK'ları her iki platformda da 4.x sürümlerine güncellendi ve otomatik olarak çözümleniyor — herhangi bir derleme değişikliğine gerek yok. iOS deployment target bu sürümle değişmeden **15.0** olarak kalmaktadır. ## Flow'ları Getirme \{#fetching-flows\} ### getPaywall → getFlow Döndürülen tür `AdaptyPaywall` yerine `AdaptyFlow` olarak değişir ve `locale` parametresi kaldırılır — bir flow render ettiğinizde locale otomatik olarak belirlenir; özel paywall'lar için tüm locale'ler `flow.remoteConfigs` içinde döner: ```diff showLineNumbers - Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") - .onSuccess { paywall -> - // use the paywall + Adapty.getFlow("YOUR_PLACEMENT_ID") + .onSuccess { flow -> + // use the flow } .onError { error -> // handle the error } ``` `getPaywallForDefaultAudience` aynı şekilde yeniden adlandırıldı: ```diff showLineNumbers - Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") + Adapty.getFlowForDefaultAudience("YOUR_PLACEMENT_ID") ``` ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` adını korur ancak artık bir `AdaptyFlow` alır: ```diff showLineNumbers - Adapty.getPaywallProducts(paywall) + Adapty.getPaywallProducts(flow) .onSuccess { products -> // use the products } ``` ## Veri modeli \{#data-model\} `getFlow`, `AdaptyPaywall` yerine `AdaptyFlow` döndürür ve nesne yapısı değişti: | v3 `AdaptyPaywall` özelliği | v4 `AdaptyFlow` özelliği | İşlem | |---|---|---| | `remoteConfig: AdaptyRemoteConfig?` (tek) | `remoteConfigs: List<AdaptyRemoteConfig>` | Bir flow, yapılandırılmış dil başına bir remote config taşır. Kullanıcıyla eşleşeni okuyun: `flow.remoteConfigs.firstOrNull { it.locale == "en" }`. | | _(yeni)_ | `paywalls: List<AdaptyFlowPaywall>` | Her giriş, flow içindeki bir paywall varyasyonudur; kendi `name`, `variationId` ve `productIdentifiers` değerlerine sahiptir. Web paywall yöntemleri bir `AdaptyFlowPaywall` alır — bkz. [Web paywall yöntemleri](#web-paywall-methods). | | `productIdentifiers` | taşındı | Ürün tanımlayıcıları artık her varyasyonda bulunur: `flow.paywalls[i].productIdentifiers`. Ürünleri getirmek için `getPaywallProducts(flow)` çağırmaya devam edin. | | `hasViewConfiguration` | kaldırıldı | Kodunuzdan tüm `hasViewConfiguration` kontrollerini kaldırın — bunun yerine `createFlowView` bir hata döndürür (bkz. [Flow'ları görüntüleme](#displaying-flows)). | `hasViewConfiguration` özelliği `AdaptyOnboarding` üzerinde kalmaya devam eder — yalnızca flow modeli bunu kaldırır. ## Web paywall metodları \{#web-paywall-methods\} `openWebPaywall` ve `createWebPaywallUrl` isimlerini korur, ancak `paywall` parametresi, `flow.paywalls` içindeki varyantlardan biri olan `AdaptyFlowPaywall` alan bir `flowPaywall` parametresiyle değiştirilir. Yine de `AdaptyPaywallProduct` geçirebilirsiniz: ```diff showLineNumbers - Adapty.openWebPaywall(paywall = paywall) + flow.paywalls.firstOrNull()?.let { flowPaywall -> + Adapty.openWebPaywall(flowPaywall = flowPaywall) + } ``` ## Flow görüntülemelerini takip etme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık bir `AdaptyFlow` alıyor. Etkinlik yine aynı varyasyon üzerinden kaydedilir; bu nedenle mevcut dönüşüm hunisi ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder. ```diff showLineNumbers - Adapty.logShowPaywall(paywall) + Adapty.logShowFlow(flow) ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülerken bu metodu çağırmanıza gerek yoktur — Adapty bu görüntülemeleri otomatik olarak takip eder. ## Flow'ları görüntüleme \{#displaying-flows\} ### createPaywallView → createFlowView Factory metodunun adını değiştirin ve `AdaptyFlow` geçirin. Dönen görünüm türü `AdaptyUIPaywallView`'dan `AdaptyUIFlowView`'a yeniden adlandırılmıştır; ancak metodları (`present`, `dismiss`) ve isteğe bağlı parametreleri (`loadTimeout`, `preloadProducts`, `customTags`, `customTimers`, `customAssets`, `productPurchaseParams`) değişmeden kalmıştır: ```diff showLineNumbers - AdaptyUI.createPaywallView(paywall) + AdaptyUI.createFlowView(flow) .onSuccess { view -> view.present() } .onError { error -> // handle the error } ``` Compose Multiplatform kullanmıyorsanız, yerel factory metodu aynı şekilde yeniden adlandırılmıştır: ```diff showLineNumbers - AdaptyUI.createNativePaywallView(paywall) + AdaptyUI.createNativeFlowView(flow) ``` `createFlowView`, flow'un yapılandırılmış bir görünümü yoksa `AdaptyResult.Error` döndürür — bu, v3'teki `hasViewConfiguration` kontrolünün yerini alır: ```diff showLineNumbers - if (paywall.hasViewConfiguration) { - AdaptyUI.createPaywallView(paywall) - .onSuccess { view -> view.present() } - } + AdaptyUI.createFlowView(flow) + .onSuccess { view -> view.present() } + .onError { error -> + // the flow has no view configured, or view creation failed + } ``` :::note Flow view tek kullanımlıktır: `dismiss()` çağrısının ardından view yok edilir, bu nedenle flow'u tekrar göstermek için `createFlowView` fonksiyonunu yeniden çağırmanız gerekir. ::: ## Olayları işleme \{#handling-events\} Olaylar gözlemcisi `AdaptyUIPaywallsEventsObserver` yerine `AdaptyUIFlowsEventsObserver` olarak yeniden adlandırıldı; callback'lerin `paywallView` ön eki de `flowView` olarak değişti. Mevcut handler gövdelerinde kod değişikliği yapmanıza gerek yok — sadece tür adını ve override'ları yeniden adlandırın: ```diff showLineNumbers - AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver { - override fun paywallViewDidFinishPurchase( - view: AdaptyUIPaywallView, + AdaptyUI.setFlowsEventsObserver(object : AdaptyUIFlowsEventsObserver { + override fun flowViewDidFinishPurchase( + view: AdaptyUIFlowView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { // custom logic after purchase } }) ``` Bir callback de yeniden adlandırıldı: `paywallViewDidFailRendering`, `flowViewDidReceiveError` oldu. Önceki rendering hatalarının yanı sıra diğer satın alma dışı çalışma zamanı hatalarında da tetiklenir: ```diff showLineNumbers - override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) {} + override fun flowViewDidReceiveError(view: AdaptyUIFlowView, error: AdaptyError) {} ``` Callback'lerin tam listesi için [Flow ve paywall olaylarını yönetme](kmp-handling-events) bölümüne bakın. ### Compose platform görünümü \{#compose-platform-view\} Compose Multiplatform composable ile görünüm gömmek istiyorsanız, `AdaptyUIPaywallPlatformView(paywall, ...)` bileşeni `AdaptyUIFlowPlatformView(flow, ...)` olarak yeniden adlandırıldı. Olay geri çağrıları `onDid...` adlarını korur; yalnızca `onDidFailRendering`, `onDidReceiveError` olarak değişti: ```diff showLineNumbers - AdaptyUIPaywallPlatformView( - paywall = paywall, + AdaptyUIFlowPlatformView( + flow = flow, onDidFinishPurchase = { view, product, result -> /* ... */ }, ) ``` v3'te olduğu gibi, burada ilettiğiniz callback'ler (ve `registerFlowEventsListener` aracılığıyla kaydedilen tüm observer'lar) global observer'ın **yerine değil, ona ek olarak** çalışır — callback'iniz bir olayı gözlemler; global varsayılanın yerini almaz. [Değişen varsayılanları](#default-behavior-changes) aklınızda bulundurun: örneğin, global varsayılan artık satın alma işleminin ardından görünümü kapatmaz. ### Yeni API'lar - `AdaptyUI.setObserverModeResolver(...)` ve `AdaptyUIObserverModeResolver` — SDK [Observer modu](implement-observer-mode-kmp)nda çalışırken flow'lardan başlatılan satın alma ve geri yükleme işlemlerini yönetir. Önceden bu yalnızca native iOS ve Android SDK'larında kullanılabilirdi. Bkz. [Observer modunda flow sunma](kmp-present-flows-in-observer-mode). - `AdaptyUI.setSystemRequestsHandler(...)` ve `AdaptyUISystemRequestsHandler` — bir flow'dan gelen sistem isteklerine ayrılmıştır (işletim sistemi izin istemleri ve uygulama değerlendirme istekleri). Flow'lar henüz bu istekleri tetiklemediğinden bir handler kaydetmenize gerek yoktur. - Yeni isteğe bağlı `flowViewDidReceiveAnalyticEvent` callback'i, bir flow'dan gelen özel analitik olayları için ayrılmıştır. Flow'lar henüz bu olayları kodunuza iletmediğinden bunu uygulamanıza gerek yoktur. - `AdaptyUI.openWebUrl(url, openIn)` ve `AdaptyUI.requestAppReview()` — bunlar varsayılan `OpenUrlAction` işlemini ve varsayılan `handleAppReviewRequest`'i destekler; böylece URL'ler ve uygulama değerlendirme istemleri kutudan çıktığı gibi native olarak işlenir. Yalnızca bu varsayılanları geçersiz kılarsanız doğrudan çağırın. - `AdaptyConfig.ServerCluster.CN` — uygulamanızı [Adapty'nin Çin sunucularına](china-cluster) bağlamak için `DEFAULT` ve `EU`'nun yanında yeni bir sunucu kümesi seçeneği. ## Varsayılan davranış değişiklikleri \{#default-behavior-changes\} Bu değişiklikler derleme hatası oluşturmaz; bu nedenle çalışma zamanında test edin: - **Satın alma tamamlama**: v3'te, varsayılan `paywallViewDidFinishPurchase`, `AdaptyPurchaseResult.UserCanceled` dışındaki her satın alma sonucunda görünümü kapatıyordu. v4'te, varsayılan `flowViewDidFinishPurchase` hiçbir şey yapmaz; yani **satın alma tamamlandıktan sonra flow, siz kapatana kadar açık kalır** — bu iOS davranışıyla örtüşür. Otomatik kapanmaya güveniyorsanız, satın alma tamamlandığında `view.dismiss()` çağrısını kendiniz yapın. - **Android sistem geri tuşu**: v3'te, varsayılan `paywallViewDidPerformAction` hem `CloseAction` hem de `AndroidSystemBackAction` üzerinde görünümü kapatıyordu. v4'te, varsayılan yalnızca `CloseAction` ile ilgilenir — **sistem geri tuşu artık flow'u tek başına kapatmaz**; bu, bir flow'un sistem hareketiyle kapatılamadığı iOS davranışıyla örtüşür. Kullanıcılara açık bir çıkış yolu sunun (bir **Kapat** düğmesi veya `on_device_back` eylemi) ya da `flowViewDidPerformAction` içinde görünümü kendiniz kapatın. - **Görünüm hataları**: v3'te, varsayılan `paywallViewDidFailRendering` hiçbir şey yapmıyordu. v4'te, varsayılan `flowViewDidReceiveError` **görünümü kapatır** — görünümü açık tutmak veya hatayı farklı ele almak istiyorsanız bu davranışı geçersiz kılın. - **Görünümler tek kullanımlıktır**: `dismiss()` çağrısından sonra görünüm yok edilir. Flow'u tekrar göstermek için `createFlowView` metodunu yeniden çağırın. ## Onboarding API'sinin Kullanımdan Kaldırılması \{#onboarding-api-deprecation\} Eski onboarding API'si, v4.0'da [Flow Builder](adapty-flow-builder) lehine kullanımdan kaldırılmıştır. Hâlâ çalışmaktadır, ancak gelecekteki bir sürümde kaldırılacaktır; bu nedenle onboarding'lerinizi Flow Builder'a taşımayı planlayın. Kullanımdan kaldırılan semboller: `getOnboarding`, `getOnboardingForDefaultAudience`, `AdaptyUI.createOnboardingView`, `AdaptyUI.createNativeOnboardingView` ve `AdaptyUIOnboardingsEventsObserver`. --- # File: migration-to-kmp-315 --- --- title: "Adapty Kotlin Multiplatform SDK 3.15.0 göç kılavuzu" description: "Adapty Kotlin Multiplatform SDK 3.15.0 için göç adımları" --- Adapty Kotlin Multiplatform SDK 3.15.0, yeni özellikler ve iyileştirmeler getiren önemli bir sürümdür; ancak bazı göç adımları uygulamanızı gerektirebilir. 1. Observer sınıfı ve metot adlarını güncelleyin. 2. Yedek paywall metot adını güncelleyin. 3. Olay işleme metotlarındaki view sınıfı adını güncelleyin. ## Observer sınıfı ve metot adlarını güncelleyin \{#update-observer-class-and-method-names\} Observer sınıfı ve kayıt metodu yeniden adlandırıldı: ```diff - import com.adapty.kmp.AdaptyUIObserver + import com.adapty.kmp.AdaptyUIPaywallsEventsObserver - import com.adapty.kmp.models.AdaptyUIView + import com.adapty.kmp.models.AdaptyUIPaywallView - class MyAdaptyUIObserver : AdaptyUIObserver { - override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { + class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { + override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { // handle actions } } // Set up the observer - AdaptyUI.setObserver(MyAdaptyUIObserver()) + AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## Yedek paywall metot adını güncelleyin \{#update-fallback-paywalls-method-name\} Yedek paywall'ları ayarlayan metot adı değiştirildi: ```diff showLineNumbers - Adapty.setFallbackPaywalls(assetId = "fallback.json") + Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` ## Olay işleme metotlarındaki view sınıfı adını güncelleyin \{#update-view-class-name-in-event-handling-methods\} Artık tüm olay işleme metotları `AdaptyUIView` yerine yeni `AdaptyUIPaywallView` sınıfını kullanıyor: ```diff - override fun paywallViewDidAppear(view: AdaptyUIView) { + override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance } - override fun paywallViewDidDisappear(view: AdaptyUIView) { + override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance } - override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { + override fun paywallViewDidSelectProduct(view: AdaptyUIView, productId: String) { // Handle product selection } - override fun paywallViewDidStartPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct) { + override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start } - override fun paywallViewDidFinishPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { + override fun paywallViewDidFinishPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { // Handle purchase result } - override fun paywallViewDidFailPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, error: AdaptyError) { + override fun paywallViewDidFailPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError) { // Add your purchase failure handling logic here } - override fun paywallViewDidFinishRestore(view: AdaptyUIView, profile: AdaptyProfile) { + override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here } - override fun paywallViewDidFailRestore(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here } - override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIView, product: AdaptyPaywallProduct?, error: AdaptyError?) { + override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError?) { // Handle web payment navigation result } - override fun paywallViewDidFailLoadingProducts(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here } - override fun paywallViewDidFailRendering(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error } ``` --- # End of Documentation _Generated on: 2026-07-24T13:02:34.382Z_ _Successfully processed: 48/48 files_ # REACT-NATIVE - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.384Z Total files: 45 --- # File: sdk-installation-react-native-expo --- --- title: "Adapty React Native SDK'yı Expo projesine kurma ve yapılandırma" description: "Abonelik tabanlı uygulamalar için Adapty React Native SDK'yı Expo projesine adım adım kurma kılavuzu." --- :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Expo'ya kurma \{#install-adapty-sdk-to-expo\} Adapty SDK çalışabilmesi için native modüllere ihtiyaç duyduğundan, Expo Go ile kullanılamaz. Bunun yerine geliştirme için [Expo Dev Client](https://docs.expo.dev/develop/development-builds/introduction/) kullanmanız gerekir. ### 1. Adapty paketlerini yükleme \{#install-adapty-packages\} Projenizin kök dizininde aşağıdaki komutu çalıştırın: ```bash title="Bash" npx expo install react-native-adapty ``` ### 2. Expo config plugin'ini yapılandırma \{#configure-expo-config-plugin\} Adapty'nin Expo config plugin'ini `app.json` veya `app.config.js` dosyanıza ekleyin: ```json title="app.json" { "expo": { "plugins": [ "react-native-adapty" ] } } ``` ### 3. Native projeyi yeniden derleme \{#rebuild-native-project\} Config plugin'ini ekledikten sonra native projeyi yeniden derlemeniz gerekir: ```bash title="Bash" npx expo prebuild --clean ``` Ardından uygulamanızı çalıştırın: <Tabs> <TabItem value="ios" label="iOS"> ```bash title="Bash" npx expo run:ios ``` </TabItem> <TabItem value="android" label="Android"> ```bash title="Bash" npx expo run:android ``` </TabItem> </Tabs> ## Adapty SDK'yı yapılandırma \{#configure-adapty-sdk\} **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. Adapty SDK'yı yapılandırmak için `activate` metodunu uygulama başlangıcında çağırın: ```typescript title="App.tsx" activateAdapty({ apiKey: 'PUBLIC_SDK_KEY' }); ``` `PUBLIC_SDK_KEY` değerini kendi Adapty public SDK anahtarınızla değiştirdiğinizden emin olun. :::warning Adapty'yi birden fazla kez başlatmayın. SDK'nın uygulama yaşam döngüsü boyunca yalnızca bir kez çağrılması gerekir. ::: ## Yedekleme kuralları \{#backup-rules\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> ## Örnek uygulama \{#sample-app\} :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: :::important Bu kılavuz, Adapty React Native SDK'sını **bir Expo projesine** kurma ve yapılandırma adımlarını ele almaktadır. **Saf React Native (Expo olmadan)** kullanıyorsanız, bunun yerine [React Native kurulum kılavuzunu](sdk-installation-react-native-pure) takip edin. ::: Adapty SDK, React Native uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu modül, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: Bu modül, platformlar arası paywall'lar oluşturmak için kullanılan, kod gerektirmeyen kullanıcı dostu bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. AdaptyUI, core modülüyle birlikte otomatik olarak etkinleştirilir. React Native uygulamanızda uygulama içi satın alma (IAP) entegrasyonunun nasıl yapılacağına dair kapsamlı bir rehber arıyorsanız [şuraya](https://adapty.io/blog/react-native-in-app-purchases-tutorial/) göz atabilirsiniz. :::tip Adapty SDK'nın bir Expo uygulamasına nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Örnek uygulamalarımıza göz atın: - Gerçek satın almalar ve Paywall Builder dahil tüm işlevsellik için [Expo dev build örneği](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) - Mock modla test etmek için [Expo Go & Web örneği](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) ::: Eksiksiz bir uygulama adım adım anlatımı için şu videoyu da izleyebilirsiniz: <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/TtCJswpt2ms?si=FlFJGvpj-U33yoNK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> ## Gereksinimler \{#requirements\} Adapty React Native SDK, iOS 15.0+ gerektirir. iOS için derleme yapmak **Swift 6.0** veya sonrasını gerektirir. [Kids Mode](kids-mode-react-native) **Swift 6.1** veya sonrasını gerektirir. :::info SDK v3.17'den itibaren Adapty SDK varsayılan olarak Google Play Billing Library v8.0.0 kullanır. ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} :::important v4'ten itibaren, Adapty React Native SDK artık yerel bağımlılıklarının CocoaPods ile kurulumunu desteklememektedir. v4 veya daha sonrasına ihtiyacınız varsa ([Flow Builder](adapty-flow-builder) için), bunun yerine aşağıdaki [Adapty SDK 4.0: Swift Package Manager'ı etkinleştirin](#adapty-sdk-40-enable-swift-package-manager) bölümünü izleyin. ::: [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-React-Native.svg?style=flat&logo=react)](https://github.com/adaptyteam/AdaptySDK-React-Native/releases) :::important Bir Expo projesinde Adapty'yi kullanmak için [Expo Dev Client](https://docs.expo.dev/versions/latest/sdk/dev-client/) (özel bir geliştirme derlemesi) gereklidir. Expo Go özel yerel modülleri desteklemez, bu yüzden onu yalnızca UI/mantık geliştirmesi için [**mock modu**](#set-up-mock-mode-for-expo-go--expo-web) ile kullanabilirsiniz (gerçek satın almalar ve AdaptyUI/Paywall Builder render'ı olmadan). ::: 1. Adapty SDK'yı yükleyin (bu, `@adapty/core`'u da otomatik olarak yükler): ```sh npx expo install react-native-adapty npx expo prebuild ``` 2. Uygulamanızı EAS veya yerel derleme kullanarak geliştirme için derleyin: <Tabs> <TabItem value="eas" label="EAS derlemesi" default> ```sh # For iOS eas build --profile development --platform ios # For Android eas build --profile development --platform android ``` </TabItem> <TabItem value="local" label="Yerel derleme"> ```sh # For iOS npx expo run:ios # For Android npx expo run:android ``` </TabItem> </Tabs> 3. Geliştirme sunucusunu başlatın: ```sh npx expo start --dev-client ``` ### Adapty SDK 4.0: Swift Package Manager'ı etkinleştir \{#adapty-sdk-40-enable-swift-package-manager\} React Native SDK 4.0 — [Flow Builder](adapty-flow-builder) desteği ekleyen bu sürüm — **React Native 0.75 veya üstü** gerektirir. SDK'yı yükleyin: ```sh npx expo install react-native-adapty@^4.0.0 ``` v4, yerel iOS SDK'larını (`Adapty`, `AdaptyUI`, `AdaptyPlugin`) CocoaPods alt bağımlılıkları yerine Swift Package Manager aracılığıyla çeker ([CocoaPods spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). SPM dinamik framework'ler gerektirir; bunları Expo'da [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/) eklentisiyle etkinleştirirsiniz. `app.json` (veya `app.config.js`) dosyasına ekleyin: ```json showLineNumbers title="app.json" { "expo": { "plugins": [ [ "expo-build-properties", { "ios": { "useFrameworks": "dynamic" } } ] ] } } ``` Ardından eklentiyi yükleyin ve yerel projeyi yeniden oluşturun: ```sh npx expo install expo-build-properties npx expo prebuild --clean ``` Tam migration için [Adapty React Native SDK'yı v4'e Taşıma](migration-to-react-native-sdk-v4) sayfasına bakın. ## Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. Adapty'yi etkinleştirmek için aşağıdaki kodu `App.tsx` dosyasına kopyalayın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıralama için [React Native SDK'da çağrı sırası](react-native-sdk-call-order) sayfasına bakın. ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, [Paywall Builder hızlı başlangıç kılavuzunu](react-native-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywall'lar için hızlı başlangıç kılavuzuna](react-native-quickstart-manual) bakın. :::tip Geliştirme ortamında aktivasyon hatalarından kaçınmak için [ipuçlarını](#development-environment-tips) inceleyin. ::: ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız AdaptyUI modülüne ihtiyacınız olacaktır. Core modülü etkinleştirdiğinizde otomatik olarak etkinleştirilir; başka bir şey yapmanıza gerek yoktur. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlükleme \{#logging\} #### Günlük sistemini ayarlayın \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki seviyeler mevcuttur: | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Yalnızca hatalar loglanır | | `warn` | Hatalar ve SDK'dan gelen kritik hatalara yol açmayan ancak dikkat edilmesi gereken mesajlar loglanır | | `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır | | `verbose` | Hata ayıklama sırasında işe yarayabilecek her türlü ek bilgi (fonksiyon çağrıları, API sorguları vb.) loglanır | Adapty yapılandırmasından önce veya yapılandırma sırasında uygulamanızda log seviyesini ayarlayabilirsiniz: ```typescript showLineNumbers title="App.tsx" // Set log level before activation // 'verbose' is recommended for development and the first production release adapty.setLogLevel('verbose'); // Or set it during configuration adapty.activate('YOUR_PUBLIC_SDK_KEY', { logLevel: 'verbose', }); ``` ### Veri politikaları \{#data-policies\} Adapty, siz açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz. Ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşımını devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özellikler uygulamanız için gerekli değilse gereksiz veri toplamayı azaltmak için bu parametreyi kullanabilirsiniz. ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ipAddressCollectionDisabled: true, }); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `ios.idfaCollectionDisabled` (iOS) veya `android.adIdCollectionDisabled` (Android) değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; App Store/Play Store politikalarına uymak, App Tracking Transparency isteğini tetiklemekten kaçınmak veya uygulamanız reklam ID'lerine dayalı attribution ya da analitik gerektirmiyorsa kullanabilirsiniz. ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, }); ``` #### AdaptyUI için medya önbelleği yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) varsayılan olarak önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. Varsayılan önbellek ayarlarını geçersiz kılmak için `mediaCache` kullanın: ```typescript adapty.activate('YOUR_PUBLIC_SDK_KEY', { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, }); ``` | Parametre | Gerekli | Açıklama | |-----------|----------|-------------| | memoryStorageTotalCostLimit | isteğe bağlı | Bellekteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer platforma göre değişir. | | memoryStorageCountLimit | isteğe bağlı | Bellek deposundaki öğe sayısı limiti. Varsayılan değer platforma göre değişir. | | diskStorageSizeLimit | isteğe bağlı | Diskteki dosya boyutu limiti (bayt cinsinden). Varsayılan değer platforma göre değişir. | ### Yerel access level'ları etkinleştirin (Android) \{#enable-local-access-levels-android\} Varsayılan olarak [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `localAccessLevelAllowed` değerini `true` olarak ayarlayın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { android: { localAccessLevelAllowed: true, }, }); ``` ### Yedekten geri yüklemede verileri temizleyin \{#clear-data-on-backup-restore\} `clearDataOnBackup` değeri `true` olarak ayarlandığında SDK, uygulamanın bir iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywalllar dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { clearDataOnBackup: true }, }); ``` ## Geliştirme ortamı ipuçları \{#development-environment-tips\} #### Expo Go / Expo Web için mock mod kurulumu \{#set-up-mock-mode-for-expo-go--expo-web\} Expo Go ve Expo Web ortamları, Adapty'nin native modüllerine erişemez. Uygulamanızın arayüzünü ve paywall mantığını geliştirip test edebilmek için çalışma zamanı hatalarından kaçınmak amacıyla Adapty, **mock mod** sunar. ::::important Mock mod, gerçek satın almaları test etmek için kullanılan bir araç **değildir**: - App Store / Google Play satın alma akışlarını **açmaz** ve gerçek işlem **oluşturmaz**. - **Adapty Paywall Builder (AdaptyUI)** ile oluşturulmuş paywall'ları/onboarding'leri **render etmez**. - Adapty'nin yerel modülleri **tamamen devre dışı bırakılır**; Xcode/Android derlemesinde eksik yerel SDK dosyaları veya geçersiz bir API anahtarı bile hata tetiklemez. Gerçek satın almaları ve Paywall Builder paywall'larını test etmek için mock modunun otomatik olarak devre dışı bırakıldığı bir Expo Dev Client / production build kullanın. :::: **Varsayılan olarak**, SDK Expo Go ve web ortamlarını otomatik olarak algılar ve sahte mod'u etkinleştirir. Sahte verileri özelleştirmek istemiyorsanız herhangi bir yapılandırma yapmanıza gerek yoktur. Sahte mod etkinken: - Tüm Adapty metodları, Adapty sunucularına ağ isteği göndermeksizin sahte veriler döndürür. - Varsayılan olarak, başlangıçtaki sahte profilin aktif aboneliği yoktur. - Varsayılan olarak, `makePurchase(...)` başarılı bir satın alma işlemini simüle eder ve premium erişim sağlar. Aktivasyon sırasında `mockConfig` kullanarak mock verileri özelleştirebilirsiniz. Konfigürasyon formatı ve desteklenen parametreler için [buraya](https://react-native.adapty.io/interfaces/adaptymockconfig) bakın. ```typescript showLineNumbers title="App.tsx" try { await adapty.activate('YOUR_PUBLIC_SDK_KEY', { mockConfig: { // Customize the initial mock profile (optional) }, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` SDK metodlarını aktivasyondan önce çağırmanız gerekiyorsa (örneğin `isActivated()` veya `setLogLevel()`), `activate()` öncesinde `enableMock()` kullanın. Bridge zaten başlatılmışsa bu metod hiçbir şey yapmaz. ```typescript showLineNumbers title="App.tsx" adapty.enableMock(); // İsteğe bağlı: mock verilerini özelleştirmek için mockConfig geçebilirsiniz // Artık aktivasyondan önce metodları çağırabilirsiniz await adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` #### Geliştirme amacıyla SDK aktivasyonunu geciktirme \{#delay-sdk-activation-for-development-purposes\} Adapty, SDK etkinleştirildiğinde tüm gerekli kullanıcı verilerini önceden alarak daha hızlı ve güncel veri erişimi sağlar. Ancak bu durum, geliştirme sırasında sıkça kimlik doğrulama isteyen iOS simülatöründe sorun çıkarabilir. Adapty, StoreKit kimlik doğrulama akışını kontrol edemese de SDK'nın güncel kullanıcı verisi almak için yaptığı istekleri erteleyebilir. `__debugDeferActivation` özelliğini etkinleştirdiğinizde, activate çağrısı bir sonraki Adapty SDK çağrısına kadar bekletilir. Bu sayede kimlik doğrulama verisi gerekmiyorsa gereksiz istemlerle karşılaşmazsınız. Bu özelliğin **yalnızca geliştirme amaçlı kullanım için tasarlandığını** belirtmek önemlidir; zira tüm olası kullanıcı senaryolarını kapsamaz. Üretim ortamında aktivasyon geciktirilmemelidir; gerçek cihazlar genellikle kimlik doğrulama verilerini hatırlar ve kullanıcıdan tekrar tekrar kimlik bilgisi girmesini istemez. Kullanım için önerilen yaklaşım şöyledir: ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __debugDeferActivation: isSimulator(), // 'isSimulator' herhangi bir 3. parti kütüphaneden }); } catch (error) { console.error('Adapty SDK etkinleştirilemedi:', error); // Uygulamanız için hatayı uygun şekilde ele alın } ``` #### React Native'in Fast Refresh özelliğinde SDK etkinleştirme hatalarını giderme \{#troubleshoot-sdk-activation-errors-on-react-natives-fast-refresh\} Adapty SDK ile React Native üzerinde geliştirme yaparken şu hatayla karşılaşabilirsiniz: `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` Bu durum, React Native'in hızlı yenileme (fast refresh) özelliğinin geliştirme sırasında birden fazla aktivasyon çağrısını tetiklemesinden kaynaklanır. Bunu önlemek için `__ignoreActivationOnFastRefresh` seçeneğini `__DEV__` (React Native'in geliştirme modu bayrağı) olarak ayarlayın. ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __ignoreActivationOnFastRefresh: __DEV__, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` ## Sorun giderme \{#troubleshooting\} #### Minimum iOS sürümü hatası \{#minimum-ios-version-error\} iOS için derleme yaparken, **minimum iOS sürümü** veya dağıtım hedefiyle ilgili bir hata görebilirsiniz. Adapty **iOS 15.0+** gerektirir. Expo, iOS projesini (`Podfile` dahil) `expo prebuild` sırasında oluşturduğundan, **`Podfile`'ı doğrudan düzenlememelisiniz**. Bunun yerine, dağıtım hedefini `expo-build-properties` yapılandırma eklentisi aracılığıyla ayarlayın. 1. Eklentiyi yükleyin: ```sh npx expo install expo-build-properties ``` 2. iOS dağıtım hedefini ayarlamak için Expo yapılandırmanızı (`app.json` veya `app.config.js`) güncelleyin: ``` { "expo": { // ...other Expo config... "plugins": [ [ "expo-build-properties", { "ios": { // Adapty requires iOS 15.0+. "deploymentTarget": "15.0" } } ], ] } } ``` 3. Yerel iOS projesini yeniden oluşturun ve yeniden derleyin: ``` npx expo prebuild --clean npx expo run:ios # or `eas build -p ios` on your CI ``` #### Android Auto Backup manifest çakışması \{#android-auto-backup-manifest-conflict\} Android Auto Backup'ı yapılandıran birden fazla SDK (Adapty, AppsFlyer veya expo-secure-store gibi) ile Expo kullanırken, bir manifest birleştirme çakışmasıyla karşılaşabilirsiniz. Tipik bir hata şöyle görünür: `Manifest merger failed : Attribute application@fullBackupContent value=(@xml/secure_store_backup_rules) from AndroidManifest.xml:24:248-306 is also present at [io.adapty:android-sdk:3.12.0] AndroidManifest.xml:9:18-70 value=(@xml/adapty_backup_rules).` Bu çakışmayı çözmek için Adapty eklentisinin Android yedekleme yapılandırmasını yönetmesine izin vermeniz gerekiyor. Projeniz aynı zamanda `expo-secure-store` kullanıyorsa, çakışmayı önlemek için kendi yedekleme kurulumunu devre dışı bırakın. `app.json` dosyanızı şu şekilde yapılandırın: ```json title="app.json" { "expo": { "plugins": [ ["react-native-adapty", { "replaceAndroidBackupConfig": true }], ["expo-secure-store", { "configureAndroidBackup": false }] ] } } ``` `replaceAndroidBackupConfig` seçeneği varsayılan olarak `false`'tur. Etkinleştirildiğinde, Adapty eklentisinin Android yedekleme kurallarını yönetmesine olanak tanır. `expo-secure-store` kullanıyorsanız uyarıları önlemek için `"configureAndroidBackup": false` ekleyin; çünkü SecureStore'un yedekleme yapılandırması artık Adapty tarafından yönetilecektir. :::important Bu kurulum yalnızca Adapty, AppsFlyer ve expo-secure-store için yedekleme gereksinimlerini dikkate alır. Projenizde başka kütüphaneler özel yedekleme kuralları tanımlıyorsa, bunları manuel olarak yapılandırmanız gerekir. ::: --- # File: sdk-installation-react-native-pure --- --- title: "Adapty SDK'yı saf bir React Native projesine yükleyin ve yapılandırın" description: "React Native'de abonelik tabanlı uygulamalar için Adapty SDK'yı adım adım yükleme kılavuzu." --- :::important Bu kılavuz yalnızca **saf React Native (Expo olmayan) projeleri** için geçerlidir. **Expo** kullanıyorsanız, bunun yerine [Expo kurulum kılavuzunu](sdk-installation-react-native-expo) takip edin. ::: Adapty SDK, React Native uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Bu modül, Adapty'nin uygulamanızda düzgün çalışması için gereklidir. - **AdaptyUI**: Bu modül, kolayca platformlar arası paywall'lar oluşturmak için kullanıcı dostu, kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir. AdaptyUI, core modülüyle birlikte otomatik olarak etkinleştirilir. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek dünya örneği görmek ister misiniz? Paywall'ları görüntüleme, satın alma yapma ve diğer temel işlevleri içeren tam kurulumu gösteren [örnek uygulamalarımıza](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples) göz atın. ::: ## Gereksinimler \{#requirements\} Adapty React Native SDK, iOS 15.0+ gerektirir. iOS için derleme yapmak **Swift 6.0** veya sonrasını gerektirir. [Kids Mode](kids-mode-react-native) **Swift 6.1** veya sonrasını gerektirir. :::info SDK v3.17'den itibaren Adapty SDK varsayılan olarak Google Play Billing Library v8.0.0 kullanır. ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} :::important v4'ten itibaren Adapty React Native SDK, yerel bağımlılıklarının CocoaPods ile kurulumunu artık desteklememektedir. v4 veya sonrasına ihtiyacınız varsa ([Flow Builder](adapty-flow-builder) için), bunun yerine aşağıdaki [Adapty SDK 4.0: Swift Package Manager'ı etkinleştirme](#adapty-sdk-40-enable-swift-package-manager) bölümünü takip edin. ::: [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-React-Native.svg?style=flat&logo=react)](https://github.com/adaptyteam/AdaptySDK-React-Native/releases) 1. Adapty SDK'yı yükleyin (bu, `@adapty/core`'u da otomatik olarak yükler): ```sh showLineNumbers title="Shell" # using npm npm install react-native-adapty # or using yarn yarn add react-native-adapty ``` 2. iOS için pod'ları yükleyin: ```sh showLineNumbers title="Shell" cd ios && pod install ``` <details> <summary>Android için, React Native sürümünüz 0.73.0'dan eskiyse (genişletmek için tıklayın)</summary> `/android/build.gradle` dosyasını güncelleyin. `kotlin-gradle-plugin:1.8.0` bağımlılığının veya daha yenisinin bulunduğundan emin olun: ```groovy showLineNumbers title="/android/build.gradle" ... buildscript { ... dependencies { ... classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0" } } ... ``` </details> ### Adapty SDK 4.0: Swift Package Manager'ı etkinleştirin \{#adapty-sdk-40-enable-swift-package-manager\} React Native SDK 4.0 — [Flow Builder](adapty-flow-builder) desteği ekleyen — **React Native 0.75 veya üstünü** gerektirir. SDK'yı yükleyin: ```sh showLineNumbers title="Shell" npm install react-native-adapty@^4.0.0 # or using yarn yarn add react-native-adapty@^4.0.0 ``` v4, yerel iOS SDK'larını (`Adapty`, `AdaptyUI`, `AdaptyPlugin`) CocoaPods alt bağımlılıkları yerine Swift Package Manager aracılığıyla çeker ([CocoaPods spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). SPM dinamik framework'ler gerektirir — `ios/Podfile` hedefine aşağıdakini ekleyin, ardından pod'ları yeniden yükleyin: ```ruby showLineNumbers title="ios/Podfile" use_frameworks! :linkage => :dynamic ``` ```sh showLineNumbers title="Shell" cd ios && pod install --repo-update ``` Daha önce `Adapty`, `AdaptyUI` veya `AdaptyPlugin`'i CocoaPods alt bağımlılıkları olarak eklediyseniz, önce `Podfile` dosyanızdan açık `pod 'Adapty'`, `pod 'AdaptyUI'` veya `pod 'AdaptyPlugin'` satırlarını kaldırın. :::warning Varsayılan statik bağlamadan dinamik framework'lere geçiş yapmak, modüler başlıkları henüz desteklemeyen kütüphanelerle çakışabilir ve Flipper ile uyumsuzdur. Ayrıntılar için [React Native SDK'yı v4'e Taşıma](migration-to-react-native-sdk-v4) sayfasına bakın. ::: ## Adapty SDK'nın Adapty modülünü etkinleştirin \{#activate-adapty-module-of-adapty-sdk\} **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. Adapty'yi etkinleştirmek için aşağıdaki kodu `App.tsx` dosyasına kopyalayın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` :::important Başka herhangi bir Adapty SDK metodunu çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıra için [React Native SDK'da çağrı sırası](react-native-sdk-call-order) sayfasına bakın. ::: Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, [Paywall Builder hızlı başlangıç kılavuzunu](react-native-quickstart-paywalls) inceleyin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywall'lar için hızlı başlangıç kılavuzuna](react-native-quickstart-manual) bakın. :::tip Geliştirme ortamında aktivasyon hatalarından kaçınmak için [ipuçlarına](#development-environment-tips) göz atın. ::: ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız AdaptyUI modülüne ihtiyacınız var. Core modülü etkinleştirdiğinizde otomatik olarak etkinleştirilir; başka bir şey yapmanıza gerek yoktur. ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlükleme \{#logging\} #### Günlükleme sistemini kurun \{#set-up-the-logging-system\} Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri günlüğe kaydeder. Aşağıdaki seviyeler mevcuttur: | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Yalnızca hatalar kaydedilir | | `warn` | Hatalar ve SDK'dan gelen kritik hatalara yol açmayan ancak dikkat edilmesi gereken mesajlar kaydedilir | | `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları kaydedilir | | `verbose` | Fonksiyon çağrıları, API sorguları gibi hata ayıklama sırasında işe yarayabilecek tüm ek bilgiler kaydedilir | Adapty yapılandırmasından önce veya yapılandırma sırasında uygulamanızda log seviyesini ayarlayabilirsiniz: ```typescript showLineNumbers title="App.tsx" // Set log level before activation // 'verbose' is recommended for development and the first production release adapty.setLogLevel('verbose'); // Or set it during configuration adapty.activate('YOUR_PUBLIC_SDK_KEY', { logLevel: 'verbose', }); ``` ### Veri politikaları \{#data-policies\} Adapty, açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz; ancak mağaza veya ülke gerekliliklerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşımını devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da IP tabanlı özelliklere ihtiyaç duymadığınız durumlarda gereksiz veri toplamayı azaltmak için bu parametreyi kullanabilirsiniz. ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ipAddressCollectionDisabled: true, }); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `ios.idfaCollectionDisabled` (iOS) veya `android.adIdCollectionDisabled` (Android) değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; App Store/Play Store politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak veya uygulamanız reklam kimliklerine dayalı attribution ya da analitik gerektirmiyorsa kullanın. ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, }); ``` #### AdaptyUI için medya önbellek yapılandırmasını ayarlayın \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, varsayılan olarak performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. Varsayılan önbellek ayarlarını geçersiz kılmak için `mediaCache` kullanın: ```typescript adapty.activate('YOUR_PUBLIC_SDK_KEY', { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, }); ``` | Parametre | Zorunlu | Açıklama | |-----------|----------|-------------| | memoryStorageTotalCostLimit | isteğe bağlı | Bellekteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer platforma göre değişir. | | memoryStorageCountLimit | isteğe bağlı | Bellek depolamasının öğe sayısı sınırı. Varsayılan değer platforma göre değişir. | | diskStorageSizeLimit | isteğe bağlı | Diskteki dosya boyutu sınırı (bayt cinsinden). Varsayılan değer platforma göre değişir. | ### Yerel access level'ları etkinleştirin (Android) \{#enable-local-access-levels-android\} Varsayılan olarak [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `localAccessLevelAllowed` değerini `true` olarak ayarlayın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { android: { localAccessLevelAllowed: true, }, }); ``` ### Yedekleme geri yüklemede verileri temizleyin \{#clear-data-on-backup-restore\} `clearDataOnBackup` değeri `true` olarak ayarlandığında SDK, uygulamanın iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywall'lar dahil tüm yerel SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { clearDataOnBackup: true }, }); ``` ## Geliştirme ortamı ipuçları \{#development-environment-tips\} #### Geliştirme amaçlı SDK aktivasyonunu geciktirme \{#delay-sdk-activation-for-development-purposes\} Adapty, SDK aktivasyonu sırasında gerekli tüm kullanıcı verilerini önceden alarak daha hızlı erişim sağlar. Ancak bu durum, geliştirme sırasında sık sık kimlik doğrulama isteyen iOS simülatöründe sorun yaratabilir. Adapty, StoreKit kimlik doğrulama akışını kontrol edemese de SDK'nın güncel kullanıcı verisi almak için yaptığı istekleri erteleyebilir. `__debugDeferActivation` özelliğini etkinleştirerek, bir sonraki Adapty SDK çağrısını yapana kadar aktivasyon çağrısı bekletilir. Bu, ihtiyaç duyulmadığında kimlik doğrulama verileri için gereksiz istemlerden kaçınmanızı sağlar. **Bu özelliğin yalnızca geliştirme amaçlı kullanıma yönelik olduğunu** belirtmek önemlidir; zira tüm olası kullanıcı senaryolarını kapsamaz. Prodüksiyonda aktivasyon geciktirilmemelidir; gerçek cihazlar genellikle kimlik doğrulama verilerini hatırlar ve kimlik bilgilerini tekrar tekrar sormaz. İşte önerilen kullanım yaklaşımı: ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __debugDeferActivation: isSimulator(), // herhangi bir 3. taraf kütüphanesinden 'isSimulator' }); } catch (error) { console.error('Adapty SDK etkinleştirilemedi:', error); // Uygulamanız için hatayı uygun şekilde ele alın } ``` #### React Native'in Fast Refresh özelliğinde SDK etkinleştirme hatalarını giderme \{#troubleshoot-sdk-activation-errors-on-react-natives-fast-refresh\} Adapty SDK ile React Native'de geliştirme yaparken şu hatayla karşılaşabilirsiniz: `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` Bu durum, React Native'in hızlı yenileme (fast refresh) özelliğinin geliştirme sürecinde birden fazla aktivasyon çağrısını tetiklemesinden kaynaklanır. Bunu önlemek için `__ignoreActivationOnFastRefresh` seçeneğini `__DEV__` (React Native'in geliştirme modu bayrağı) olarak ayarlayın. ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __ignoreActivationOnFastRefresh: __DEV__, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` #### Yerel test için mock modu kurma \{#set-up-mock-mode-for-local-testing\} Yerel geliştirme ve test süreçlerinde, sandbox App Store/Google Play hesaplarına ihtiyaç duymadan hızlı iterasyon yapabilmek için mock modunu etkinleştirebilirsiniz. Mock modu, Adapty'nin native modüllerini tamamen devre dışı bırakarak simüle edilmiş veriler döndürür. :::important Mock modu, gerçek satın almaları test etmek için bir araç **değildir**: - App Store / Google Play satın alma akışlarını **açmaz** ve gerçek işlem **oluşturmaz**. - **Adapty Paywall Builder (AdaptyUI)** ile oluşturulan paywall'ları/onboarding'leri **render etmez**. - Adapty'nin yerel modülleri **tamamen atlanır**; Xcode/Android derlemesinde yerel SDK dosyalarının eksik olması veya geçersiz bir API anahtarı hata tetiklemez. - Adapty sunucularına hiçbir veri gönderilmez. Gerçek satın almaları ve Paywall Builder paywall'larını test etmek için mock modunu devre dışı bırakın ve sandbox hesapları kullanın. ::: Mock modunu etkinleştirmek için `enableMock` değerini `true` olarak ayarlayın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { enableMock: true, }); ``` Mock modu etkinken: - Tüm Adapty metodları, Adapty sunucularına ağ isteği göndermeden sahte veriler döndürür. - Varsayılan olarak, başlangıç mock profili aktif abonelik içermez. - Varsayılan olarak, `makePurchase(...)` başarılı bir satın alma simüle eder ve premium erişim sağlar. Mock verilerini, aktivasyon sırasında `mockConfig` kullanarak özelleştirebilirsiniz. Yapılandırma formatı ve desteklenen parametreler için [buraya](https://react-native.adapty.io/interfaces/adaptymockconfig) bakın. ```typescript showLineNumbers title="App.tsx" try { await adapty.activate('YOUR_PUBLIC_SDK_KEY', { mockConfig: { // Customize the initial mock profile (optional) }, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` Aktivasyondan önce SDK metodlarını çağırmanız gerekiyorsa (örneğin `isActivated()` veya `setLogLevel()`), `activate()` öncesinde `enableMock()` kullanın. Köprü zaten başlatılmışsa bu metod hiçbir şey yapmaz. ```typescript showLineNumbers title="App.tsx" adapty.enableMock(); // Optional: pass mockConfig to customize mock data // Now you can call methods before activation await adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` ## Sorun giderme \{#troubleshooting\} #### Minimum iOS sürümü hatası \{#minimum-ios-version-error\} Minimum iOS sürümü hatası alırsanız, Podfile'ınızı güncelleyin: ```diff -platform :ios, min_ios_version_supported +platform :ios, '15.0' ``` #### Android Auto Backup manifest çakışması \{#android-auto-backup-manifest-conflict\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> #### Android'de başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} Satın alma akışını başlatan Activity varsayılan olmayan bir `launchMode` kullanıyorsa, kullanıcı Google Play'den, bir bankacılık uygulamasından veya bir tarayıcıdan döndüğünde Android onu hatalı şekilde yeniden oluşturabilir veya yeniden kullanabilir. Bu, satın alma sonucunun kaybolmasına veya iptal edilmiş olarak değerlendirilmesine neden olabilir. Satın almaların doğru çalışmasını sağlamak için, satın alma akışını başlatan Activity için yalnızca `standard` veya `singleTop` launch mode'larını kullanın ve diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma akışını başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile SWIFT_VERSION geçersiz kılmasının neden olduğu Swift 6 derleme hataları \{#swift-6-build-errors-caused-by-podfile-swift_version-override\} React Native uygulamanızı iOS için derlerken, Adapty pod hedeflerinde Swift 6 derleme hatalarıyla karşılaşabilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içindeki `@Sendable` uyumsuzlukları, Adapty türlerinde eksik `Sendable` uyumu veya actor izolasyon hataları yer alır. Adapty pod'ları `s.swift_version = '6.0'` bildirir ve derlenmek için Swift 6 gerektirir. Kendi uygulama kodunuz Swift 5'te kalabilir — yalnızca Adapty pod hedeflerinin (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`, `AdaptyLogger`, `AdaptyPlugin`) Swift 6 ile derlenmesi gerekir. En yaygın neden, `ios/Podfile` içinde her pod hedefi için `SWIFT_VERSION`'ı yeniden yazan bir `post_install` kancasıdır: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **Düzeltme**: Adapty pod hedeflerini geçersiz kılmanın dışında bırakın: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` Ardından `ios/` dizininden `pod install` komutunu çalıştırın ve yeniden derleyin. Doğrulamak için `ios/Pods/Pods.xcodeproj` dosyasını açın, `Adapty` pod hedefini seçin → **Build Settings** → **Swift Language Version**. Bu değer **Swift 6** olmalıdır. --- # File: react-native-quickstart-paywalls --- --- title: "React Native SDK'da Flow Builder ile satın almaları etkinleştirme" description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmeye yönelik hızlı başlangıç rehberi." --- Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Flow'lar**](adapty-flow-builder) – kullanıcılara ürünleri sunan, kod gerektirmeyen Flow Builder'da oluşturulan ekran dizileri. SDK bunları `getFlow` aracılığıyla getirir. Arayüzü kendi kodunuzda oluşturmayı tercih ederseniz, bunun yerine bir paywall kullanın — bkz. [Paywall'ları manuel olarak uygulama](react-native-quickstart-manual). - [**Placement'lar**](placements) – flow'ları uygulamanızda nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'sine göre istersiniz. Bu, A/B testleri çalıştırmayı ve farklı kullanıcılara farklı flow'lar göstermeyi kolaylaştırır. Adapty, uygulamanızda satın almaları etkinleştirmek için üç farklı yöntem sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama yöntemi | Karmaşıklık | Ne zaman kullanılır | |---|---|---| | Adapty Flow Builder | ✅ Kolay | [Kod gerektirmeyen builder'da eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm karmaşık satın alma sürecini, makbuz doğrulamasını ve abonelik yönetimini arka planda halleder. | | Manuel olarak oluşturulan paywall'lar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda uygularsınız, ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine de Adapty'den alırsınız. Bkz. [rehber](react-native-quickstart-manual). | | Gözlemci modu | 🔴 Zor | Kendi satın alma yönetim altyapınız zaten var ve onu kullanmaya devam etmek istiyorsunuz. Gözlemci modunun Adapty'de bazı sınırlamaları olduğunu unutmayın. Bkz. [makale](observer-vs-full-mode). | :::important **Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl uygulanacağını gösterir.** Paywall arayüzünü kendiniz oluşturmayı tercih ederseniz, bkz. [Paywall'ları manuel olarak uygulama](react-native-quickstart-manual). ::: Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir: 1. **Flow'u alın**: Onu Adapty'den alın. 2. **Görüntüleyin, satın almaları Adapty sizin için halleder**: View'i uygulamanızda gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini, uygulamanızın bunlara vereceği yanıtla ilişkilendirin. Örneğin, kullanıcılar butonlara tıkladığında bağlantıları açın veya flow'u kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Adapty Kontrol Paneli'nde uygulamanızı [App Store](initial_ios) ve/veya [Google Play](initial-android) ile bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir flow oluşturun ve ona ürünler ekleyin](create-paywall). 4. [Bir placement oluşturun ve flow'unuzu ona ekleyin](create-placement). 5. Uygulama kodunuzda [Adapty SDK'yı yükleyin ve etkinleştirin](sdk-installation-reactnative). Bu rehber Adapty React Native SDK v4 API'lerini kullanır. ## 1. Flow'u alın \{#1-get-the-flow\} Flow'larınız, kontrol panelinde yapılandırılan placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testleri](ab-tests) çalıştırmanıza olanak tanır. Adapty Flow Builder'da oluşturulan bir flow'u almak için, `getFlow` metodunu kullanarak `flow` nesnesini [placement](placements) ID'siyle alın. Flow, onu görüntülemek için gereken arayüz öğelerini ve stilini içerir. ```typescript showLineNumbers title="React Native" try { const flow = await adapty.getFlow('YOUR_PLACEMENT_ID'); // the requested flow } catch (error) { // handle the error } ``` ## 2. Flow'u görüntüleyin \{#2-display-the-flow\} Artık flow'a sahip olduğunuzda, onu görüntülemek için birkaç satır eklemeniz yeterlidir. <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> Bir flow'u mevcut bileşen ağacınıza gömmek için, `AdaptyFlowView` bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın: ```typescript showLineNumbers title="React Native (TSX)" function MyFlow({ flow }) { const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>( (result, product) => result.type !== 'user_cancelled', [], ); return ( <AdaptyFlowView flow={flow} style={{ flex: 1 }} onPurchaseCompleted={onPurchaseCompleted} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Flow'u bağımsız bir ekran olarak görüntülemek için, `createFlowView` metoduyla bir `view` oluşturun, olay işleyicilerini ayarlayın, ardından `view.present()` çağırın. Her `view` yalnızca bir kez kullanılabilir. Flow'u tekrar görüntülemeniz gerekirse, yeni bir `view` örneği oluşturmak için `createFlowView`'u bir kez daha çağırın. ```typescript showLineNumbers title="React Native" try { const view = await createFlowView(flow); view.setEventHandlers({ onPurchaseCompleted(result, product) { return result.type !== 'user_cancelled'; }, }); await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> :::tip Bir flow'u görüntüleme hakkında daha fazla ayrıntı için [rehberimize](react-native-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#3-handle-button-actions\} Kullanıcılar flow'daki butonlara tıkladığında, React Native SDK satın almaları, geri yüklemeyi, flow'u kapatmayı ve URL açmayı otomatik olarak yönetir. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve kodunuzda eylem yönetimi gerektirir. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz. Örneğin, kapatma butonunun varsayılan davranışı aşağıdadır. Bunu kodda eklemeniz gerekmez, ancak gerekirse nasıl yapıldığını burada görebilirsiniz. <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, eylemleri doğrudan `AdaptyFlowView` bileşeninde yönetin: ```typescript showLineNumbers title="React Native (TSX)" function MyFlow({ flow }) { const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>( () => true, // allow the flow to close [], ); const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>( (actionId) => false, [], ); return ( <AdaptyFlowView flow={flow} style={{ flex: 1 }} onCloseButtonPress={onCloseButtonPress} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için `setEventHandlers` kullanarak olay işleyicilerini uygulayın: ```typescript showLineNumbers title="React Native" const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; // allow the flow to close }, }); ``` </TabItem> </Tabs> :::tip Buton [aksiyonlarını](react-native-handle-paywall-actions) ve [olaylarını](react-native-handling-events-1) nasıl yöneteceğinizle ilgili kılavuzlarımızı okuyun. ::: ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Flow'unuz uygulamada görüntülenmeye hazır. Flow'dan bir test satın alması tamamlayabildiğinizden emin olmak için [satın almalarınızı test edin](react-native-test). Şimdi, doğru kullanıcılara bir flow gösterdiğinizden veya ücretli özelliklere erişim verdiğinizden emin olmak için [kullanıcıların access level'ını kontrol etmeniz](react-native-check-subscription-status) gerekir. ## Tam örnek \{#full-example\} Bu rehberdeki tüm adımların uygulamanızda birlikte nasıl entegre edilebileceği aşağıdadır. <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> ```javascript showLineNumbers title="React Native (TSX)" export default function FlowScreen() { const [flow, setFlow] = useState(null); const loadFlow = async () => { try { const flowData = await adapty.getFlow('YOUR_PLACEMENT_ID'); setFlow(flowData); } catch (error) { console.warn('Error loading flow:', error); } }; const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>( () => true, [], ); const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>( (result, product) => result.type !== 'user_cancelled', [], ); useEffect(() => { loadFlow(); }, []); return ( <View style={{ flex: 1 }}> {flow ? ( <AdaptyFlowView flow={flow} style={{ flex: 1 }} onCloseButtonPress={onCloseButtonPress} onPurchaseCompleted={onPurchaseCompleted} /> ) : ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="Load Flow" onPress={loadFlow} /> </View> )} </View> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> ```javascript showLineNumbers title="React Native" export default function FlowScreen() { const showFlow = async () => { try { const flow = await adapty.getFlow('YOUR_PLACEMENT_ID'); const view = await createFlowView(flow); view.setEventHandlers({ onCloseButtonPress() { return true; }, onPurchaseCompleted(result, product) { return result.type !== 'user_cancelled'; }, }); await view.present(); } catch (error) { // handle any error that may occur during the process console.warn('Error showing flow:', error); } }; // you can add a button to manually trigger the flow for testing purposes return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="Show Flow" onPress={showFlow} /> </View> ); } ``` </TabItem> </Tabs> --- # File: react-native-check-subscription-status --- --- title: "React Native SDK'da abonelik durumunu kontrol etme" description: "Adapty ile React Native uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriğe erişip erişemeyeceğine veya bir paywall görmesi gerekip gerekmediğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir. Bu makalede, kullanıcılara paywall mı göstereceğinize yoksa ücretli özelliklere erişim mi tanıyacağınıza karar vermek için profil durumuna nasıl erişeceğiniz anlatılmaktadır. ## Abonelik durumunu alma \{#get-subscription-status\} Kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken profilindeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var: - Anlık olarak en güncel profil verisine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) veya güncellemeyi zorlamak istediğinizde `getProfile` çağrısı yapın. - Abonelik durumu değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** ayarlayın. ### Profili alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. Profil değişikliklerini dinlemek amacıyla `adapty.addEventListener('onLatestProfileLoad')` kullanın. Adapty, kullanıcının abonelik durumu her değiştiğinde bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncellenen profil verilerini saklayın; böylece ek ağ istekleri yapmadan uygulama genelinde kullanabilirsiniz. ```javascript class SubscriptionManager { private currentProfile: any = null; constructor() { // Listen for profile updates adapty.addEventListener('onLatestProfileLoad', (profile) => { this.currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() hasAccess(): boolean { return this.currentProfile?.accessLevels?.['premium']?.isActive ?? false; } } ``` :::note Adapty, uygulamanız başladığında `onLatestProfileLoad` olay dinleyicisini otomatik olarak çağırır ve cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verilerini sağlar. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim tanıma konusunda anlık kararlar vermeniz gerektiğinde kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girilmesi veya belirli içerikler gösterilmeden önce gibi senaryolar için kullanışlıdır. ```javascript const checkAccessLevel = async () => { try { const profile = await adapty.getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive === true; } catch (error) { console.warn('Error checking access level:', error); return false; // Show paywall if access check fails } }; const initializePaywall = async () => { try { await loadPaywall(); const hasAccess = await checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } catch (error) { console.warn('Error initializing paywall:', error); } }; ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların satın aldıkları şeylere erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](react-native-quickstart-identify) öğrenin. --- # File: react-native-quickstart-identify --- --- title: "React Native SDK'da kullanıcıları tanımlama" description: "React Native'de uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa size göre hazırlanmıştır. Burada, Adapty'deki kullanıcı profilleriyle mevcut kimlik doğrulama sisteminizi nasıl uyumlu hale getireceğinizi öğreneceksiniz. ::: Kullanıcıların satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız backend kimlik doğrulaması kullanmıyor ve kullanıcı verisi saklamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanızda backend kimlik doğrulaması varsa (veya olacaksa), [tanımlanmış kullanıcılar bölümüne](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Profiller anonim **(customer user ID'siz)** veya tanımlanmış **(customer user ID'li)** olabilir. - Adapty'deki profilleri kendi kimlik doğrulama sisteminizle eşleştirmek için **customer user ID** sağlarsınız. Anonim ve tanımlanmış kullanıcılar arasındaki farklar şöyledir: | | Anonim kullanıcılar | Tanımlanmış kullanıcılar | |-------------------------|--------------------------------------------------------------|---------------------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar arasında aynı profil | | **Veri kalıcılığı** | Anonim kullanıcıların verileri uygulama kurulumuna bağlıdır | Tanımlanmış kullanıcıların verileri uygulama kurulumları arasında kalıcı olarak saklanır | ## Anonim kullanıcılar \{#anonymous-users\} Backend kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. Uygulamanın ilk açılışında SDK etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada herhangi bir şey satın aldığında, bu satın alma **Adapty profiliyle ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **etkinleştirmede yeni bir anonim profil oluşturur**. 4. Kullanıcı uygulamanızda daha önce satın alma yaptıysa, SDK etkinleştirildiğinde satın almalar varsayılan olarak App Store'dan otomatik olarak senkronize edilir. Anonim kullanıcılarda her kurulumda yeni profil oluşturulur, ancak bu sorun değildir; çünkü Adapty analitiğinde [yeni kurulum olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). :::note Yedekten geri yükleme işlemleri, yeniden yüklemelerden farklı davranır. Varsayılan olarak, bir kullanıcı yedekten geri yükleme yaptığında SDK önbelleğe alınan verileri korur ve yeni bir profil oluşturmaz. Bu davranışı `clearDataOnBackup` ayarıyla yapılandırabilirsiniz. [Daha fazla bilgi edinin](sdk-installation-react-native-pure#clear-data-on-backup-restore). ::: Anonim kullanıcılar için kurulumları **cihaz ID'lerine** göre saymanız gerekir. Bu durumda, yeniden yüklemeler dahil olmak üzere bir cihaza yapılan her uygulama kurulumu bir kurulum olarak sayılır. ## Tanımlanmış kullanıcılar \{#identified-users\} Uygulamadaki kullanıcıları tanımlamak için iki seçeneğiniz var: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra giriş yapıyorsa, kimlik doğruladıklarında bir customer user ID ile `identify()` çağırın. - [**SDK etkinleştirme sırasında:**](#during-the-sdk-activation) Uygulama başladığında zaten bir customer user ID saklıyorsanız, `activate()` çağrısında bunu gönderin. :::important Varsayılan olarak, Adapty başka bir Customer User ID ile ilişkili bir Customer User ID'den satın alma aldığında, access level paylaşılır ve her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Ayrıntılar için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kayıt olduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty onu otomatik olarak mevcut profile bağlar. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı kimlikleri her kullanıcı için benzersiz olmalıdır. Parametre değerini sabit kodlarsanız, tüm kullanıcılar aynı kişi olarak değerlendirilir. ::: Diğer SDK metodlarını çağırmadan önce her zaman `identify` işlemini `await` ile bekleyin. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar ya da anonim profile düşer. Bkz. [React Native SDK'da çağrı sırası](react-native-sdk-call-order). ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Her kullanıcı için benzersiz // successfully identified } catch (error) { // handle the error } ``` ### SDK etkinleştirme sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify`'ı ayrıca çağırmak yerine bunu `activate` metodunda gönderebilirsiniz. Customer user ID biliyorsanız ancak bunu yalnızca etkinleştirmeden sonra ayarlıyorsanız, etkinleştirme sırasında Adapty yeni bir anonim profil oluşturacak ve `identify` çağrısından sonra mevcut profile geçecektir. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane gönderebilirsiniz. Yeni bir tane gönderirseniz, etkinleştirme sırasında oluşturulan yeni profil otomatik olarak customer user ID'ye bağlanır. :::note Varsayılan olarak, anonim profil oluşturma, kurulumlar cihaz ID'lerine göre sayıldığı için analitik panolarını etkilemez. Bir cihaz ID'si, cihazdaki mağazadan yapılan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, bunun ilk mi yoksa tekrar mı yükleme olduğundan ya da mevcut bir customer user ID kullanılıp kullanılmadığından bağımsızdır. Profil oluşturma (SDK etkinleştirme veya oturum kapatma sırasında), giriş yapma veya uygulamayı yeniden yüklemeden yükseltme, ek kurulum olayı oluşturmaz. Kurulumları cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın. ::: ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID" // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. }); ``` ### Kullanıcıların oturumunu kapatma \{#log-users-out\} Kullanıcıların oturumunu kapatmak için bir butonunuz varsa, `logout` metodunu kullanın. :::important Kullanıcının oturumunu kapatmak, kullanıcı için yeni bir anonim profil oluşturur. ::: ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` :::info Kullanıcıları uygulamaya tekrar giriş yaptırmak için `identify` metodunu kullanın. ::: ### Giriş yapmadan satın almaya izin verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıktan sonra erişimlerini koruyacaklarından emin olmanız gerekir: 1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil ID'siyle ilişkilendirir. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin, satın alma kayıt öncesinde yapıldıysa), Adapty customer user ID'yi mevcut profile atar ve tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profille bağlantılıysa), profil değişikliğinden sonra gerçek access level'ı almanız gerekir. Tanımlamanın hemen ardından [`getProfile`](react-native-check-subscription-status) çağırabilir veya verilerin otomatik senkronize edilmesi için [profil güncellemelerini dinleyebilirsiniz](react-native-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını hayata geçirdiniz! Uygulama monetizasyonunuzda başarılar dileriz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboarding'ler**](react-native-onboardings): Onboarding'lerle kullanıcıları etkileyin ve elde tutma oranını artırın - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analitik hizmetleriyle entegre olun - [**Özel profil özellikleri ayarlama**](react-native-setting-user-attributes): Kullanıcı profillerine özel özellikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-react-native --- --- title: "SDK entegrasyon becerisini kullanarak Adapty'yi React Native uygulamanıza entegre edin" description: "Adapty SDK'sını React Native uygulamanıza baştan sona entegre etmek için AI kodlama aracınızla adapty-sdk-integration becerisini kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu beceri beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, [adım adım entegrasyon kılavuzunu](adapty-cursor-react-native) takip edin — AI aracınızı her aşamada doğru belgelerle yönlendirir. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-react-native --- --- title: "Adapty'yi AI yardımıyla React Native uygulamanıza entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi React Native uygulamanıza adım adım entegre etme kılavuzu." --- Bu kılavuz, bir yapay zeka kodlama aracıyla React Native uygulamanıza Adapty'yi adım adım entegre etmenizi anlatıyor — doğru Adapty dokümanlarını doğru sırayla besleyerek ilerleyebilirsiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı yapılandırmalar yapılmasını gerektirir. Bunu etkileşimli bir LLM aracıyla ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Skill yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI skill, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywall'larınızı ve placement'larınızı doğrudan ayarlamasını sağlar — her adım için Kontrol Paneli'ni açmanıza gerek kalmaz. Yalnızca Kontrol Paneli'nde [mağazalarınızı bağlamanız](integrate-payments) yeterlidir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Skill eklendikten sonra agent'ınızda `/adapty-cli` komutunu çalıştırın. Mağazalarınızı bağlamak için Kontrol Paneli'ni ne zaman açmanız gerektiği de dahil olmak üzere her adımda sizi yönlendirecektir. ### Kontrol Paneli Yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, herhangi bir kod yazmadan önce bunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için bulamaz; bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Uygulamanız her iki platformu da hedefliyorsa App Store ve Google Play'i bağlayın. Satın almaların çalışması için bu gereklidir. [Uygulama mağazalarını bağla](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin ve **API keys** bölümünü bulun. Kodda bu, `adapty.activate("YOUR_PUBLIC_SDK_KEY")` çağrısına geçirdiğiniz string'dir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere koddan doğrudan erişmenize gerek yok — Adapty bunları paywall'lar aracılığıyla iletir. [Ürün ekle](quickstart-products) 4. **Paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasında bir paywall oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `adapty.getPaywall("YOUR_PLACEMENT_ID")` fonksiyonuna geçirdiğiniz string değerdir. [Paywall oluştur](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde, **Products** sayfasından her ürün için yapılandırın. Kodda, `profile.accessLevels['premium']?.isActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne göre farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Beşine de sahip olduğunuzda, kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'im Y" — böylece doğru başlatma ve paywall çekme kodunu üretebilir. ::: ### Hazır olduğunuzda kurulum \{#set-up-when-ready\} Kodlamaya başlamak için bunlar gerekli değildir, ancak entegrasyonunuz olgunlaştıkça bunlara ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getPaywall` çağrısı ekleyin. - **Analitik entegrasyonlar**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonlar](analytics-integration) ve [attribution entegrasyonlar](attribution-integration). ## LLM'inize Adapty Dokümanlarını Besleyin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi Kullanın (önerilen) [Context7](https://context7.com), LLM'inizin güncel Adapty belgelerine doğrudan erişmesini sağlayan bir MCP sunucusudur. LLM'iniz, sorduğunuz şeye göre doğru belgeleri otomatik olarak getirir — URL yapıştırmanıza gerek kalmaz. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurulum için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, kullandığınız editörü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, Adapty kütüphanesine prompt'larınızda şu şekilde referans verin: ``` Use the adaptyteam/adapty-docs library to look up how to install the React Native SDK ``` :::warning Context7, dok bağlantılarını elle yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalıştığından emin olmak için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Her Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** butonuna tıklayın. Örnek: [adapty-cursor-react-native.md](https://adapty.io/docs/tr/adapty-cursor-react-native.md). Aşağıdaki [uygulama adım adım rehberindeki](#implementation-walkthrough) her adım, yapıştırabileceğiniz `.md` bağlantılarını içeren "LLM'inize gönderin" bloğu içerir. Daha fazla dokümanı aynı anda görüntülemek için aşağıdaki [indeks dosyaları ve platforma özgü alt kümeler](#plain-text-doc-index-files) bölümüne bakın. ## Uygulama adım adım rehberi \{#implementation-walkthrough\} Bu rehberin geri kalanı, Adapty entegrasyonunu uygulama sırasına göre adım adım ele alır. Her aşamada LLM'inize göndereceğiniz belgeler, tamamlandığında ne görmeniz gerektiği ve sık karşılaşılan sorunlar açıklanmaktadır. ### Entegrasyonunuzu planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), LLM'nin herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, izlemesi gereken kılavuzları etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin no-code builder'ında paywall'lar oluşturursunuz ve SDK bunları otomatik olarak render eder. - [**Manuel oluşturulan paywall'lar**](react-native-making-purchases): Kendi paywall arayüzünüzü kodla oluşturursunuz, ancak ürünleri almak ve satın almaları yönetmek için yine de Adapty'yi kullanırsınız. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](react-native-quickstart-paywalls) okuyun. ### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\} Adapty SDK bağımlılığını npm (veya yarn) ile ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temel adımdır — geri kalan her şey buna bağlıdır. Expo ve saf React Native projeleri için ayrı kurulum kılavuzlarımız var — kurulumunuza uyan kılavuzu seçin. **Kılavuzlar:** - [Expo ile kurulum](sdk-installation-react-native-expo) - [Saf React Native ile kurulum](sdk-installation-react-native-pure) :::tip[Checkpoint] - **Beklenen:** Uygulama hem iOS hem Android'de derleniyor ve çalışıyor. Metro bundler loglarında Adapty aktivasyon logu görünüyor. - **Dikkat:** "Public API key is missing" → **App settings** bölümündeki gerçek anahtarınızla placeholder'ı değiştirdiğinizi kontrol edin. ::: ### Paywallları göster ve satın almaları yönet \{#show-paywalls-and-handle-purchases\} Placement ID ile bir paywall getir, göster ve satın alma olaylarını yönet. İhtiyacın olan kılavuzlar, satın almaları nasıl yönettiğine göre değişir. Her satın almayı ilerlerken sandbox'ta test et — sona bırakma. Kurulum talimatları için [Sandbox'ta satın almaları test et](test-purchases-in-sandbox) sayfasına bak. <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **Kılavuzlar:** - [Paywall'lar ile satın alımları etkinleştirme (hızlı başlangıç)](react-native-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını getirme](react-native-get-pb-paywalls) - [Paywall'ları görüntüleme](react-native-present-paywalls) - [Paywall olaylarını işleme](react-native-handling-events-1) - [Buton eylemlerine yanıt verme](react-native-handle-paywall-actions) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/react-native-quickstart-paywalls.md - https://adapty.io/docs/tr/react-native-get-pb-paywalls.md - https://adapty.io/docs/tr/react-native-present-paywalls.md - https://adapty.io/docs/tr/react-native-handling-events-1.md - https://adapty.io/docs/tr/react-native-handle-paywall-actions.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Paywall, yapılandırılmış ürünlerinizle birlikte görünür. Bir ürüne dokunulduğunda sandbox satın alma iletişim kutusu açılır. - **Dikkat:** Boş paywall veya `getPaywall` hatası → placement ID'nin kontrol panelindeki ile tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manuel paywalllar"> **Kılavuzlar:** - [Özel paywallınızda satın almaları etkinleştirme (hızlı başlangıç)](react-native-quickstart-manual) - [Paywall ve ürünleri getirme](fetch-paywalls-and-products-react-native) - [Remote config ile tasarlanmış paywall'ı render etme](present-remote-config-paywalls-react-native) - [Satın alma yapma](react-native-making-purchases) - [Satın almaları geri yükleme](react-native-restore-purchase) Read these Adapty docs before writing code: - https://adapty.io/docs/tr/react-native-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-react-native.md - https://adapty.io/docs/tr/present-remote-config-paywalls-react-native.md - https://adapty.io/docs/tr/react-native-making-purchases.md - https://adapty.io/docs/tr/react-native-restore-purchase.md :::tip[Checkpoint] - **Beklenen:** Özel paywallınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikliyor. - **Sorun:** Boş ürünler dizisi → paywallın kontrol panelinde ürünler atandığını ve placement'ın bir kitleye sahip olduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Observer mode"> **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode-react-native) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode-react-native) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-react-native.md - https://adapty.io/docs/tr/report-transactions-observer-mode-react-native.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak yapılan bir sandbox satın alımının ardından işlem, Adapty kontrol panelinin **Event Feed** bölümünde görünmelidir. - **Dikkat:** Hiç event gelmiyorsa → işlemleri Adapty'ye raporladığınızı ve her iki store için de sunucu bildirimlerinin yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol etme \{#check-subscription-status\} Bir satın alma işleminden sonra, premium içeriğe erişimi kısıtlamak için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin. **Kılavuz:** [Abonelik durumunu kontrol etme](react-native-check-subscription-status) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/react-native-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın alma işleminin ardından `profile.accessLevels['premium']?.isActive` değeri `true` döner. - **Dikkat:** Satın alma sonrasında `accessLevels` boş geliyorsa → kontrol panelinde ürüne bir access level atandığından emin olun. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Satın almaların cihazlar arasında korunması için uygulama kullanıcı hesaplarını Adapty profillerine bağlayın. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](react-native-quickstart-identify) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/react-native-quickstart-identify.md ``` :::tip[Checkpoint] - **Beklenen:** `adapty.identify("your-user-id")` çağrısının ardından, kontrol panelindeki **Profiles** bölümü özel kullanıcı ID'nizi gösterir. - **Dikkat:** Anonim profil attribution sorununu önlemek için `identify` fonksiyonunu aktivasyondan sonra, paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlık \{#prepare-for-release\} Entegrasyonunuz sandbox ortamında çalışır hale geldiğinde, her şeyin production'a hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Kılavuz:** [Yayın kontrol listesi](release-checklist) Bunu LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Checkpoint] - **Beklenen:** Tüm kontrol listesi öğeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Sunucu bildirimleri eksik → App Store Server Notifications'ı **App settings → iOS SDK** bölümünde, Google Play Real-Time Developer Notifications'ı ise **App settings → Android SDK** bölümünde yapılandırın. ::: ## Düz metin doküman indeks dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty belgelerini listeleyen veya birleştiren indeks dosyaları barındırıyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. Web sitelerini LLM'lere erişilebilir kılmak için [gelişmekte olan bir standart](https://llmstxt.org/). Bazı yapay zeka ajanları (ör. ChatGPT) için `llms.txt` dosyasını indirip sohbete dosya olarak yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Adapty dokümantasyon sitesinin tamamı tek bir dosyada birleştirilmiş hali. Çok büyük — yalnızca tüm içeriğe ihtiyaç duyduğunuzda kullanın. - React Native'e özel [`react-native-llms.txt`](https://adapty.io/docs/tr/react-native-llms.txt) ve [`react-native-llms-full.txt`](https://adapty.io/docs/tr/react-native-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: react-native-get-pb-paywalls --- --- title: "Flow'ları ve paywall'ları getirme - React Native" description: "React Native uygulamanızda Adapty'den flow'ları ve paywall'ları getirin." --- <SDKv4> <MethodPromo method="getFlow" /> [Flow'unuzu veya Paywall Builder paywall'ınızı tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda görüntüleyebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'ı ve view yapılandırmasını almaktır. Lütfen bu konunun flow'lara ve Paywall Builder ile özelleştirilen paywall'lara atıfta bulunduğunu unutmayın. Paywall'larınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywall'ları için paywall'ları ve ürünleri getirme](fetch-paywalls-and-products-react-native) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları ve paywall'ları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ona dahil edin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ona dahil edin](create-placement). 4. Mobil uygulamanızda [Adapty SDK'yı](sdk-installation-reactnative) yükleyin. </details> ## Flow/paywall getirme \{#fetch-flowpaywall\} Bir flow veya paywall'ı Flow Builder veya Paywall Builder kullanarak tasarladıysanız, onu kullanıcıya göstermek için mobil uygulama kodunuzda render etme derdine girmenize gerek yoktur. Böyle bir flow veya paywall, hem içinde ne gösterileceğini hem de nasıl gösterileceğini içerir. Yine de, placement aracılığıyla ID'sini ve view yapılandırmasını almanız, ardından onu mobil uygulamanızda sunmanız gerekir. Flow veya paywall'ı getirin ve [view](react-native-get-pb-paywalls#fetch-the-view-configuration)'ini mümkün olduğunca erken oluşturun — ideal olarak onu sunmadan çok önce. `createFlowView` metodu, view yapılandırmasını yükler ve görsellerini arka planda indirip önbelleğe almaya başlar. Onu ne kadar erken çağırırsanız, bu indirmelerin tamamlanması için o kadar çok zaman olur. Flow veya paywall'ı sunduğunuzda, yapılandırması ve görselleri zaten önbelleğe alınmış ve görüntülenmeye hazır olabilir. Bir flow veya paywall almak için `getFlow` metodunu kullanın: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlow(placementId); // the requested flow/paywall } catch (error) { // handle the error } ``` Parametreler: | Parametre | Zorunlu | Açıklama | |-------------------|--------|-----------| | **placementId** | gerekli | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu varyantı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın istikrarsız internetle uğraştığını düşünüyorsanız, önbelleğe alınmış veriler varsa onları döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar mutlak en son verileri alamayabilir, ancak internet bağlantıları ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Uygulamayı yeniden başlattığınızda önbelleğin bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Ayrıca paywall'ları daha hızlı getirmek için CDN'i ve CDN erişilemez olduğunda bağımsız bir yedek sunucuyu kullanırız. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman paywall'larınızın en son sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>Bu değer, bu metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa, önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun, işlem alt katmanda farklı isteklerden oluşabileceği için `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.</p><p>Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla (`5.seconds` gibi, burada `.seconds`, `import com.adapty.utils.seconds`'ten gelir) veya `TimeInterval.seconds(5)` ile oluşturabilirsiniz. Sınırlama olmaması için `TimeInterval.INFINITE` kullanın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Flow'un tanımlayıcılarını (`id`, `variationId`), adını, placement'ını, paywall varyasyonlarını (`paywalls`) ve varsa remote config'lerini (`remoteConfigs`) içeren bir `AdaptyFlow` nesnesi. | ## View yapılandırmasını getirme \{#fetch-the-view-configuration\} :::important Builder'da **Show on device** geçiş düğmesini etkinleştirdiğinizden emin olun. Bu seçenek açık değilse, view yapılandırması alınamaz. ::: Placement **Flow Builder**'da veya **Paywall Builder**'da tasarlandıysa, Adapty arayüzü sizin için render eder. View'i `createFlowView` ile oluşturun, ardından [flow veya paywall'ı sunun](react-native-present-paywalls). Placement, Builder arayüzü olmayan özel bir paywall ise, bunun yerine [onu bir remote config paywall'ı olarak yönetin](present-remote-config-paywalls-react-native). React Native SDK'da `createFlowView`'u doğrudan çağırın — önce view yapılandırmasını getirmenize gerek yoktur. :::warning `createFlowView` metodunun sonucu yalnızca bir kez kullanılabilir. Onu tekrar kullanmanız gerekirse, `createFlowView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak, `AdaptyUIError.viewAlreadyPresented` hatasıyla sonuçlanabilir. ::: ```typescript showLineNumbers try { const view = await createFlowView(flow); } catch (error) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | zorunlu | İstenen flow/paywall için bir controller elde etmek amacıyla kullanılan `AdaptyFlow` nesnesi. | | **customTags** | isteğe bağlı | Özel etiketler ve çözümlenmiş değerlerinden oluşan bir sözlük tanımlar. Özel etiketler içerikte yer tutucu işlevi görür; flow/paywall içinde kişiselleştirilmiş içerik sunmak için belirli dizelerle dinamik olarak değiştirilir. Daha fazla bilgi için Paywall Builder'da özel etiketler konusuna bakın. | | **prefetchProducts** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için etkinleştirin. `true` olarak ayarlandığında AdaptyUI gerekli ürünleri otomatik olarak çeker. Varsayılan: `false`. | | **android.enableSafeArea** | isteğe bağlı | Yalnızca Android (iOS'ta yoksayılır). İç içe nesne olarak geçirin: `android: { enableSafeArea: true }`. `true` olduğunda flow görünümü güvenli alan dolguları uygular. Modal sunum için varsayılan `true`'dur (`createFlowView` + `present()`), yerleşik `AdaptyFlowView` bileşeni için ise `false`'tur. Varsayılan değer çoğu durum için uygundur. | :::note Birden fazla dil kullanıyorsanız, bir [flow yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve locale kodlarını doğru şekilde kullanmayı [buradan](react-native-localizations-and-locale-codes) öğrenin. ::: View'e sahip olduğunuzda, [flow/paywall'ı sunun](react-native-present-paywalls). ## Daha hızlı getirmek için varsayılan bir kitle için flow veya paywall alma \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle flow'lar ve paywall'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve placement'ınız olduğu ve kullanıcılarınızın zayıf internet bağlantısı olduğu durumlarda, bir flow veya paywall'ı getirmek istediğinizden daha uzun sürebilir. Bu tür durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın flow veya paywall'ını **All Users** kitlesi için getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow/paywall getirme](#fetch-flowpaywall) bölümünde ayrıntılı olarak açıklandığı gibi flow veya paywall'ı `getFlow` metoduyla getirmek olduğunu anlamak çok önemlidir. :::warning `getFlow` kullanmanızı neden öneriyoruz `getFlowForDefaultAudience` metodu birkaç önemli dezavantajla birlikte gelir: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmemiş paywall'larla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da kişiselleştirilmiş hedeflemeyi kaybettiğiniz anlamına gelir (ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı olanlar dahil). Daha hızlı flow veya paywall getirmeden yararlanmak için bu dezavantajları kabul etmeye istekliyseniz, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde, [yukarıda](#fetch-flowpaywall) açıklanan `getFlow`'a bağlı kalın. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlowForDefaultAudience(id); // the requested flow/paywall } catch (error) { // handle the error } ``` | Parametre | Zorunlu | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | gerekli | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nizde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu varyantı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın istikrarsız internetle uğraştığını düşünüyorsanız, önbelleğe alınmış veriler varsa onları döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar mutlak en son verileri alamayabilir, ancak internet bağlantıları ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Uygulamayı yeniden başlattığınızda önbelleğin bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla temizlendiğini unutmayın.</p> | ## Asset'leri özelleştirme \{#customize-assets\} Flow/paywall'ınızdaki görselleri ve videoları özelleştirmek için özel asset'leri uygulayın. Hero görsellerinin ve videolarının önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir asset paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için, Adapty kontrol panelinde [özel bir ID ayarlamanız](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterme. - Uzak bir ana görsel yüklenirken yerel bir önizleme görseli gösterme. - Bir videoyu çalıştırmadan önce bir önizleme görseli gösterme. :::important Bu özelliği kullanmak için Adapty React Native SDK'yı 3.8.0 veya daha yüksek bir sürüme güncelleyin. ::: Basit bir sözlük aracılığıyla özel varlıkları nasıl sağlayabileceğinize dair bir örnek: ```javascript const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; view = await createFlowView(flow, { customAssets }) ``` :::note Bir asset bulunamazsa, flow/paywall varsayılan görünümüne geri döner. ::: </SDKv4> <SDKv3> Adapty Kontrol Paneli'nde yeni Paywall Builder ile [paywall'ınızın görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, onu mobil uygulamanızda görüntüleyebilirsiniz. Bu süreçteki ilk adım, aşağıda açıklandığı gibi placement ile ilişkili paywall'ı ve view yapılandırmasını almaktır. :::warning Yeni Paywall Builder, React Native SDK sürüm 3.0 veya üzeriyle çalışır. ::: Lütfen bu konunun Paywall Builder ile özelleştirilen paywall'lara atıfta bulunduğunu unutmayın. Paywall'larınızı manuel olarak uyguluyorsanız, lütfen [Mobil uygulamanızda remote config paywall'ları için paywall'ları ve ürünleri getirme](fetch-paywalls-and-products-react-native) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall'ları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ona dahil edin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı ona dahil edin](create-placement). 4. Mobil uygulamanızda [Adapty SDK'yı](sdk-installation-reactnative) yükleyin. </details> ## Paywall Builder ile tasarlanan paywallı çekme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda render etme konusunda endişelenmenize gerek yoktur. Bu tür bir paywall, paywall içinde neyin gösterileceğini ve nasıl gösterileceğini içerir. Yine de placement aracılığıyla ID'sini, görünüm yapılandırmasını alıp ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, kullanıcılara sunmadan önce görsellerin indirilmesine yeterli zaman tanımak amacıyla paywall ve [görünüm yapılandırmasını](react-native-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız önemlidir. Bir paywall almak için `getPaywall` metodunu kullanın: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywall(placementId, locale); // the requested paywall } catch (error) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |-------------------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil içindir, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) konusuna bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere sahip olmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internetle karşılaştığını düşünüyorsanız, önbellekte veri varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı almak için CDN ve CDN'e ulaşılamadığı durumlarda bağımsız bir yedek sunucu da kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywalllarınızın her zaman en son sürümünü almanızı sağlamak için tasarlanmıştır.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>Bu değer, bu metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa, önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem perde arkasında farklı isteklerden oluşabilir.</p><p>Android için: `TimeInterval`'ı uzantı fonksiyonlarıyla oluşturabilirsiniz (örneğin `5.seconds`, `.seconds` burada `import com.adapty.utils.seconds` içindendir) veya `TimeInterval.seconds(5)`. Sınırlama olmadan ayarlamak için `TimeInterval.INFINITE` kullanın.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesi. | ## Paywall Builder kullanılarak tasarlanan paywallın görünüm yapılandırmasını çekme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse, görünüm yapılandırması alınamaz. ::: Paywall'u çektikten sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu, paywallı nasıl görüntüleyeceğiniz konusunda size rehberlik edecektir. `ViewConfiguration` mevcutsa, bunu bir Paywall Builder paywall'u olarak ele alın; değilse, [bunu bir remote config paywall'u olarak işleyin](present-remote-config-paywalls-react-native). React Native SDK'da, görünüm yapılandırmasını manuel olarak önceden çekmeden doğrudan `createPaywallView` metodunu çağırın. :::warning `createPaywallView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa, `createPaywallView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına neden olabilir. ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createPaywallView} from 'react-native-adapty/dist/ui'; if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { //use your custom logic } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir controller almak üzere kullanılan `AdaptyPaywall` nesnesi. | | **customTags** | isteğe bağlı | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlar. Özel etiketler, paywall içeriğinde yer tutucu olarak kullanılır ve paywall içinde kişiselleştirilmiş içerik sağlamak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için Paywall Builder'da Özel Etiketler konusuna bakın. | | **prefetchProducts** | isteğe bağlı | Ekrandaki ürünlerin görüntülenme zamanlamasını optimize etmek için etkinleştirin. `true` olarak ayarlandığında AdaptyUI, gerekli ürünleri otomatik olarak getirir. Varsayılan: `false`. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve yerel ayar kodlarını doğru şekilde nasıl kullanacağınızı [buradan](react-native-localizations-and-locale-codes) öğrenin. ::: Görünümü aldıktan sonra, [paywall'u sunun](react-native-present-paywalls). ## Daha hızlı çekmek için varsayılan kitle için paywall alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Genellikle paywalllar neredeyse anında çekilir, dolayısıyla bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywallınız olduğu ve kullanıcılarınızın zayıf bir internet bağlantısına sahip olduğu durumlarda, bir paywall çekmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın paywallını **Tüm Kullanıcılar** kitlesi için çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılandırıldığı gibi `getPaywall` metoduyla paywall çekmek olduğunu anlamak önemlidir. :::warning `getPaywall` kullanmanızı neden öneriyoruz `getPaywallForDefaultAudience` metodu birkaç önemli dezavantajla birlikte gelir: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için (mevcut ve gelecekteki) farklı paywalllar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalacaksınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmemiş paywalllarla sorun yaşayabileceğini kabul edeceksiniz. - **Hedefleme kaybı**: Tüm kullanıcılar **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywall'u görecek; bu da kişiselleştirilmiş hedeflemeyi (ülkeler, pazarlama attribution veya kendi özel özelliklerinize dayalı hedefleme dahil) kaybetmeniz anlamına gelir. Daha hızlı paywall çekme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metoduna bağlı kalın. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note `getPaywallForDefaultAudience` metodu, React Native SDK 2.11.2 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil içindir, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](react-native-localizations-and-locale-codes) konusuna bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verilere sahip olmasını sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internetle karşılaştığını düşünüyorsanız, önbellekte veri varsa önbelleğe alınmış verileri döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yoluyla silindiğini unutmayın.</p> | ## Varlıkları özelleştirme \{#customize-assets\} Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görselleri ve videolarının önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leri aracılığıyla hedefler ve davranışlarını özelleştirirsiniz. Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID ayarlamanız](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görsel veya video gösterme. - Uzak ana görsel yüklenirken yerel bir önizleme görseli gösterme. - Bir video çalıştırmadan önce önizleme görseli gösterme. :::important Bu özelliği kullanmak için, Adapty React Native SDK'yı sürüm 3.8.0 veya üzerine güncelleyin. ::: Özel asset'leri basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek: ```javascript const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; view = await createPaywallView(paywall, { customAssets }) ``` :::note Bir asset bulunamazsa, paywall varsayılan görünümüne geri döner. ::: </SDKv3> --- # File: react-native-present-paywalls --- --- title: "Flow'ları ve paywall'ları görüntüleme - React Native" description: "Adapty ile React Native uygulamanızda kullanıcılara flow'ları ve paywall'ları sunun." --- <SDKv4> <MethodPromo method="getFlow" label="Flow'ları ve paywall'ları görüntüleme" /> Flow Builder'da bir flow veya paywall oluşturduysanız, onu kullanıcıya göstermek için mobil uygulama kodunuzda render etme derdine girmenize gerek yoktur. Böyle bir flow, hem içinde ne gösterileceğini hem de nasıl gösterileceğini içerir. Başlamadan önce şunlardan emin olun: 1. Bir [flow veya paywall oluşturdunuz](create-paywall). 2. Onu bir [placement](placements)'a eklediniz. 3. [Flow'u getirdiniz ve view'i hazırladınız](react-native-get-pb-paywalls). :::warning Bu rehber yalnızca **flow'lar ve Paywall Builder paywall'ları** içindir; bunlar SDK v4.0 veya sonrasını gerektirir. Flow sunma süreci, remote config paywall'ları için farklıdır. - **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls). ::: Adapty React Native SDK, flow'ları ve paywall'ları sunmak için iki yol sağlar: - **React bileşeni**: Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır. - **Modal sunum** ## React bileşeni \{#react-component\} Bir flow'u mevcut bileşen ağacınıza gömmek için, `AdaptyFlowView` bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın. Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır. :::tip `AdaptyFlowView` bileşeni, view'ini render edildiğinde oluşturur; yani yapılandırma ve görseller yüklendiğinde. Bunları önceden yüklemek için, uygulamanızda daha erken bir noktada aynı flow için [`createFlowView`](react-native-get-pb-paywalls#fetch-the-view-configuration) çağırın. Bileşen daha sonra önbelleğe alınmış verileri yeniden kullanır ve indirmeleri beklemeden render eder. ::: ```typescript showLineNumbers title="React Native (TSX)" function MyFlow({ flow }) { const flowParams = useMemo(() => ({ loadTimeoutMs: 3000, }), []); const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<FlowEventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<FlowEventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<FlowEventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<FlowEventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<FlowEventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<FlowEventHandlers['onRestoreFailed']>((error) => {}, []); const onAppeared = useCallback<FlowEventHandlers['onAppeared']>(() => {}, []); const onError = useCallback<FlowEventHandlers['onError']>((error) => {}, []); const onLoadingProductsFailed = useCallback<FlowEventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<FlowEventHandlers['onUrlPress']>((url) => {}, []); const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<FlowEventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyFlowView flow={flow} params={flowParams} style={styles.flow} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onAppeared={onAppeared} onError={onError} onLoadingProductsFailed={onLoadingProductsFailed} onCustomAction={onCustomAction} onUrlPress={onUrlPress} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` ## Modal sunum \{#modal-presentation\} Bir flow'u bağımsız bir ekran olarak görüntülemek için, [`createFlowView`](react-native-get-pb-paywalls#fetch-the-view-configuration) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Flow'u tekrar görüntülemeniz gerekirse, yeni bir `view` örneği oluşturmak için `createFlowView`'u bir kez daha çağırın. :::warning Aynı `view`'i yeniden oluşturmadan tekrar kullanmak yasaktır. Bu, bir `AdaptyUIError.viewAlreadyPresented` hatasıyla sonuçlanır. ::: ```typescript showLineNumbers title="React Native (TSX)" const view = await createFlowView(flow); // Optional: handle flow events (close, purchase, restore, etc) // view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` :::important `setEventHandlers`'ı birden çok kez çağırmak, sağladığınız işleyicileri geçersiz kılar; söz konusu belirli olaylar için hem varsayılan hem de önceden ayarlanmış işleyicilerin yerini alır. ::: ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} Flow'un iOS'ta nasıl sunulacağını, `present()` metoduna `iosPresentationStyle` parametresini ileterek yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## Geliştirici tanımlı zamanlayıcı kullanımı \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için, bu örnekte `CUSTOM_TIMER_NY` olan `timerId`'yi kullanın; bu, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. Bu sayede uygulamanız zamanlayıcıyı doğru değerle dinamik olarak günceller; örneğin `13g 09s 03d 34s` (zamanlayıcının bitiş zamanı olan Yılbaşı'ndan mevcut zamanın çıkarılmasıyla hesaplanır). <Tabs> <TabItem value="component" label="React bileşeni"> ```typescript showLineNumbers title="React Native (TSX)" const flowParams = { customTimers: { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } }; <AdaptyFlowView flow={flow} params={flowParams} // ... your event handlers /> ``` </TabItem> <TabItem value="modal" label="Modal sunum"> ```typescript showLineNumbers title="React Native (TSX)" const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createFlowView(flow, { customTimers }); ``` </TabItem> </Tabs> Bu örnekte `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar; örneğin `13g 09s 03d 34s` (zamanlayıcının bitiş zamanı olan Yılbaşı'ndan mevcut zamanın çıkarılmasıyla hesaplanır). ## Diyalog gösterme \{#show-dialog\} Android'de bir flow view sunulduğunda, yerel uyarı diyalogları yerine bu metodu kullanın. Android'de normal RN uyarıları flow view'in arkasında görünür, bu da onları kullanıcılara görünmez kılar. Bu metot, tüm platformlarda diyalogun flow'un üzerinde düzgün şekilde sunulmasını sağlar. ```typescript showLineNumbers title="React Native (TSX)" try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the flow await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## Bir aboneliği başka biriyle değiştirme \{#replace-one-subscription-with-another\} Android'de başka bir abonelik etkinken bir kullanıcı yeni bir abonelik satın almaya çalıştığında, flow view'i oluştururken abonelik güncelleme parametrelerini geçirerek yeni satın almanın nasıl yönetileceğini kontrol edebilirsiniz. Mevcut aboneliği yenisiyle değiştirmek için, `createFlowView` içinde `oldSubVendorProductId` ve `prorationMode` parametreleriyle birlikte `productPurchaseParams` kullanın. ```typescript showLineNumbers title="React Native (TSX)" const productPurchaseParams = flow.paywalls .flatMap((variation) => variation.productIdentifiers) .map((productId) => { let params = {}; if (Platform.OS === 'android') { params.android = { subscriptionUpdateParams: { oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION', prorationMode: 'with_time_proration', }, }; } return { productId, params }; }); const view = await createFlowView(flow, { productPurchaseParams }); ``` </SDKv4> <SDKv3> Paywall Builder kullanarak bir paywall özelleştirdiyseniz, onu kullanıcıya göstermek için mobil uygulama kodunuzda render etme derdine girmenize gerek yoktur. Böyle bir paywall, hem paywall içinde ne gösterileceğini hem de nasıl gösterileceğini içerir. Başlamadan önce şunlardan emin olun: 1. Bir [paywall oluşturdunuz](create-paywall). 2. Paywall'ı bir [placement](placements)'a eklediniz. 3. [Paywall'ı getirdiniz ve view'i hazırladınız](react-native-get-pb-paywalls). :::warning Bu rehber yalnızca **yeni Paywall Builder paywall'ları** içindir; bunlar SDK v3.0 veya sonrasını gerektirir. Paywall sunma süreci, Paywall Builder'ın farklı sürümleriyle tasarlanan paywall'lar ve remote config paywall'ları için farklıdır. - **Remote config paywall'larını** sunmak için bkz. [Remote config ile tasarlanan paywall'ı render etme](present-remote-config-paywalls). ::: Adapty React Native SDK, paywall'ları sunmak için iki yol sağlar: - **React bileşeni**: Gömülü bileşen, onu uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır. - **Modal sunum** ## React bileşeni \{#react-component\} :::note **React bileşeni** yaklaşımı SDK 3.14.0 veya üstünü gerektirir. ::: Bir paywallı mevcut bileşen ağacınıza gömmek için `AdaptyPaywallView` bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın. Gömülü bileşen, uygulamanızın mimarisine ve navigasyon sistemine entegre etmenize olanak tanır. :::note Android'de, paywall durum çubuğunun arkasına uzanmıyorsa üst kısmında görsel bir katman belirebiilir. Paywalllarınız için bunu kapatmanızı öneririz. Bkz. [Paywallın üst kısmındaki görsel katman (Android)](#visual-overlay-at-the-top-of-the-paywall-android). ::: ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const paywallParams = useMemo(() => ({ loadTimeoutMs: 3000, }), []); const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []); const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []); const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []); const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => {}, []); const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyPaywallView paywall={paywall} params={paywallParams} style={styles.paywall} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onPaywallShown={onPaywallShown} onRenderingFailed={onRenderingFailed} onLoadingProductsFailed={onLoadingProductsFailed} onCustomAction={onCustomAction} onUrlPress={onUrlPress} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` ## Modal sunum \{#modal-presentation\} Bir paywallı bağımsız bir ekran olarak göstermek için, [`createPaywallView`](react-native-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywallı tekrar göstermeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `createPaywallView`'i bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak yasaktır. Bu durum `AdaptyUIError.viewAlreadyPresented` hatasına yol açar. ::: ```typescript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); // Optional: handle paywall events (close, purchase, restore, etc) // view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` :::important `setEventHandlers`'ı birden çok kez çağırmak, sağladığınız işleyicileri geçersiz kılar; söz konusu belirli olaylar için hem varsayılan hem de önceden ayarlanmış işleyicilerin yerini alır. ::: ### iOS sunum stilini yapılandırın \{#configure-ios-presentation-style\} Paywall'ın iOS'ta nasıl sunulacağını, `present()` metoduna `iosPresentationStyle` parametresini ileterek yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## Geliştirici tanımlı zamanlayıcı kullanma \{#use-developer-defined-timer\} Mobil uygulamanızda geliştirici tanımlı zamanlayıcılar kullanmak için, `timerId`'yi kullanın; bu örnekte, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'si olan `CUSTOM_TIMER_NY`. Bu, uygulamanızın zamanlayıcıyı `13d 09h 03m 34s` gibi doğru değerle dinamik olarak güncellemesini sağlar (zamanlayıcının bitiş zamanı, örneğin Yılbaşı Günü, eksi mevcut zaman olarak hesaplanır). <Tabs> <TabItem value="component" label="React bileşeni"> ```typescript showLineNumbers title="React Native (TSX)" const paywallParams = { customTimers: { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } }; <AdaptyPaywallView paywall={paywall} params={paywallParams} // ... your event handlers /> ``` </TabItem> <TabItem value="modal" label="Modal sunum"> ```typescript showLineNumbers title="React Native (TSX)" const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createPaywallView(paywall, { customTimers }); ``` </TabItem> </Tabs> Bu örnekte, `CUSTOM_TIMER_NY`, Adapty kontrol panelinde ayarladığınız geliştirici tanımlı zamanlayıcının **Timer ID**'sidir. `timerResolver`, uygulamanızın zamanlayıcıyı `13d 09h 03m 34s` gibi doğru değerle dinamik olarak güncellemesini sağlar (zamanlayıcının bitiş zamanı, örneğin Yılbaşı Günü, eksi mevcut zaman olarak hesaplanır). ## Dialog gösterme \{#show-dialog\} Android'de bir paywall view sunulduğunda, yerel uyarı dialogları yerine bu metodu kullanın. Android'de normal RN uyarıları paywall view'ın arkasında kalır ve kullanıcılar tarafından görülemez. Bu metot, tüm platformlarda paywallın üzerinde dialog'un düzgün şekilde sunulmasını sağlar. ```typescript showLineNumbers title="React Native (TSX)" try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## Bir aboneliği diğeriyle değiştirme \{#replace-one-subscription-with-another\} Bir kullanıcı Android'de başka bir abonelik aktifken yeni bir abonelik satın almaya çalıştığında, paywall view'ı oluştururken abonelik güncelleme parametrelerini ileterek yeni satın almanın nasıl işleneceğini kontrol edebilirsiniz. Mevcut aboneliği yenisiyle değiştirmek için `createPaywallView`'de `oldSubVendorProductId` ve `prorationMode` parametreleriyle birlikte `productPurchaseParams` kullanın. ```typescript showLineNumbers title="React Native (TSX)" const productPurchaseParams = paywall.productIdentifiers.map((productId) => { let params = {}; if (Platform.OS === 'android') { params.android = { subscriptionUpdateParams: { oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION', prorationMode: 'with_time_proration', }, }; } return { productId, params }; }); const view = await createPaywallView(paywall, { productPurchaseParams }); ``` ## Sorun giderme \{#troubleshooting\} ### Paywallın üst kısmındaki görsel katman (Android) \{#visual-overlay-at-the-top-of-the-paywall-android\} :::note Bu ayar React Native SDK 3.15.5'ten itibaren desteklenmektedir ve yalnızca bare React Native projelerinde kullanılabilir. Expo yönetilen iş akışı kullanıyorsanız bu Android kaynağını doğrudan ekleyemezsiniz. Bu ayarı uygulamak için, ilgili Android kaynağını ekleyen özel bir Expo config plugin oluşturmanız ve bunu app.config.js'e kaydetmeniz gerekir. Bunun nedeni Expo'nun yerel Android projesini sizin adınıza yönetmesidir. ::: `AdaptyPaywallView` durum çubuğunun arkasına uzanmıyorsa, üst kısmında yine de görsel bir kaplama görünebilir. Onu kaldırmak için uygulamanıza aşağıdaki boolean kaynağını ekleyin: 1. `android/app/src/main/res/values` konumuna gidin. `bools.xml` dosyası yoksa oluşturun. 2. Aşağıdaki kaynağı ekleyin: ```xml <resources> <bool name="adapty_paywall_enable_safe_area_paddings">false</bool> </resources> ``` Değişikliklerin uygulamanızdaki tüm paywall'lar için genel olarak geçerli olduğunu unutmayın. </SDKv3> --- # File: react-native-handle-paywall-actions --- --- title: "Flow eylemlerine yanıt verme - React Native" description: "Daha iyi uygulama para kazanımı için Adapty kullanarak React Native'de flow'lardan ve paywall'lardan gelen buton eylemlerini yönetin." --- <SDKv4> Adapty Flow Builder veya Paywall Builder kullanarak flow'lar veya paywall'lar oluşturuyorsanız, butonları doğru şekilde ayarlamanız çok önemlidir: 1. [Flow/paywall builder'da bir buton](paywall-buttons) ekleyin ve ona ya mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi yönetmek için uygulamanızda kod yazın. Bu rehber, özel ve mevcut eylemleri kodunuzda nasıl yöneteceğinizi gösterir. :::warning **Satın almalar, geri yüklemeler, flow/paywall kapatma işlemleri ve URL açma otomatik olarak yönetilir.** Bunların varsayılan davranışını yapılandırabilir veya özel eylemler için yanıtlar uygulayabilirsiniz. ::: :::note SDK, push bildirimleri veya kamera erişimi gibi sistem izni istekleri için bir `onRequestPermission` flow işleyicisi sunar. Flow'lar bu istekleri henüz tetiklemez, bu yüzden şimdilik uygulamanıza gerek yoktur. ::: ## Flow'ları ve paywall'ları kapatma \{#close-flows-and-paywalls\} Flow'unuzu veya paywall'ınızı kapatacak bir buton eklemek için: 1. Builder'da bir buton ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda, flow veya paywall'ı kapatan `close` eylemi için bir işleyici uygulayın. :::info React Native SDK'da `close` eylemi varsayılan olarak flow veya paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir flow'u kapatmak başka birini açmayı tetikleyebilir. ::: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, kapatma eylemini tekil olay işleyici prop'ları aracılığıyla yönetin: ```javascript function MyPaywall({ flow }) { const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>(() => { // Handle close button press - navigate away or hide component navigation.goBack(); }, [navigation]); return ( <AdaptyFlowView flow={flow} style={styles.container} onCloseButtonPress={onCloseButtonPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için, kapatma işleyicisini uygulayın: ```javascript const view = await createFlowView(flow); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; // allow flow or paywall closing } }); ``` </TabItem> </Tabs> ## Flow'lardan ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve onu **Open URL** eylemine sahip butonlarla aynı şekilde yönetin. ::: Flow'unuzdan veya paywall'ınızdan bir bağlantı açan bir buton eklemek için (örneğin **Kullanım koşulları** veya **Gizlilik politikası**): 1. Builder'da bir buton ekleyin, ona **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi bir tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. :::info React Native SDK'da `openUrl` eylemi varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, URL açmayı olay işleyici prop'u aracılığıyla yönetin: ```javascript function MyPaywall({ flow }) { const onUrlPress = useCallback<FlowEventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); return ( <AdaptyFlowView flow={flow} style={styles.container} onUrlPress={onUrlPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için, URL işleyicisini uygulayın: ```javascript const view = await createFlowView(flow); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { Linking.openURL(url); return false; // Keep flow or paywall open }, }); ``` </TabItem> </Tabs> ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer herhangi bir eylemi yöneten bir buton eklemek için: 1. Builder'da bir buton ekleyin, ona **Custom** eylemini atayın ve bir ID atayın. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifleri veya tek seferlik satın alma grubunuz varsa, başka bir flow veya paywall görüntüleyecek bir buton ekleyebilirsiniz: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, özel eylemleri olay işleyici prop'u aracılığıyla yönetin: ```javascript function MyPaywall({ flow }) { const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>((actionId) => { if (actionId === 'openNewPaywall') { // Display another flow or paywall } }, []); return ( <AdaptyFlowView flow={flow} style={styles.container} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> Modal sunum için, özel eylem işleyicilerini uygulayın: ```javascript const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another flow or paywall } }, }); ``` </TabItem> </Tabs> </SDKv4> <SDKv3> Adapty paywall builder kullanarak paywall'lar oluşturuyorsanız, butonları doğru şekilde ayarlamanız çok önemlidir: 1. [Paywall builder'da bir buton](paywall-buttons) ekleyin ve ona ya mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Atadığınız her eylemi yönetmek için uygulamanızda kod yazın. Bu rehber, özel ve mevcut eylemleri kodunuzda nasıl yöneteceğinizi gösterir. :::warning **Yalnızca satın almalar, geri yüklemeler, paywall kapatma işlemleri ve URL açma otomatik olarak yönetilir.** Diğer tüm buton eylemleri, uygulama kodunda uygun yanıt uygulamasını gerektirir. ::: ## Paywall'ları kapatma \{#close-paywalls\} Paywall'ınızı kapatacak bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Close** eylemini atayın. 2. Uygulama kodunuzda, paywall'ı kapatan `close` eylemi için bir işleyici uygulayın. :::info React Native SDK'da `close` eylemi varsayılan olarak paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywall'ı kapatmak başka birini açmayı tetikleyebilir. ::: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, kapatma eylemini tekil olay işleyici prop'ları aracılığıyla yönetin: ```javascript function MyPaywall({ paywall }) { const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => { // Handle close button press - navigate away or hide component navigation.goBack(); }, [navigation]); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCloseButtonPress={onCloseButtonPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için, kapatma işleyicisini uygulayın: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; // allow paywall closing } }); ``` </TabItem> </Tabs> ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (ör. kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** aksiyonuna sahip butonlarla aynı şekilde yönetin. ::: Paywall'ınızdan bir bağlantı açacak bir buton eklemek için (ör. **Kullanım Koşulları** veya **Gizlilik Politikası**): 1. Paywall builder'da bir buton ekleyin, **Open URL** aksiyonunu atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` aksiyonu için bir handler uygulayın. :::info React Native SDK'da `openUrl` eylemi varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. ::: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, URL açmayı olay işleyici prop'u aracılığıyla yönetin: ```javascript function MyPaywall({ paywall }) { const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onUrlPress={onUrlPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> Modal sunum için, URL işleyicisini uygulayın: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, }); ``` </TabItem> </Tabs> ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıları uygulamanıza giriş yaptıran bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin ve ona **Login** eylemini atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` eylemi için bir işleyici uygulayın. <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, girişi olay işleyici prop'u aracılığıyla yönetin: ```javascript function MyPaywall({ paywall }) { const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => { if (actionId === 'login') { navigation.navigate('Login'); } }, [navigation]); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için, giriş işleyicisini uygulayın: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'login') { navigation.navigate('Login'); } } }); ``` </TabItem> </Tabs> ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer herhangi bir eylemi yöneten bir buton eklemek için: 1. Paywall builder'da bir buton ekleyin, ona **Custom** eylemini atayın ve bir ID atayın. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifleri veya tek seferlik satın alma grubunuz varsa, başka bir paywall görüntüleyecek bir buton ekleyebilirsiniz: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için, özel eylemleri olay işleyici prop'u aracılığıyla yönetin: ```javascript function MyPaywall({ paywall }) { const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => { if (actionId === 'openNewPaywall') { // Display another paywall } }, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için, özel eylem işleyicilerini uygulayın: ```javascript const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall } }, }); ``` </TabItem> </Tabs> </SDKv3> --- # File: react-native-handling-events-1 --- --- title: "Flow ve paywall olaylarını yönetme - React Native" description: "Adapty SDK ile React Native uygulamanızda flow ve paywall olaylarını yönetin." --- <SDKv4> :::important Bu rehber; satın almalar, geri yüklemeler, ürün seçimi ve flow render işlemleri için olay yönetimini kapsar. Ayrıca buton yönetimini de (flow'u kapatma, bağlantı açma, özel eylemler vb.) ayarlayabilirsiniz. Ayrıntılar için [buton eylemlerini yönetme rehberimize](react-native-handle-paywall-actions) bakın. ::: Flow Builder ile oluşturulan flow'lar ve paywall'lar, satın alma yapmak ve geri yüklemek için ekstra koda ihtiyaç duymaz. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamalarını (kapatma butonları, URL'ler, ürün seçimleri vb.) ve flow üzerinde gerçekleştirilen satın almayla ilgili eylemlere ait bildirimleri içerir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin. Mobil uygulamanızda flow ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için olay işleyicilerini uygulayın: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için olayları, `AdaptyFlowView` bileşenindeki tekil olay işleyici prop'ları aracılığıyla yönetirsiniz: ```typescript showLineNumbers title="React Native (TSX)" function MyFlow({ flow }) { const onCloseButtonPress = useCallback<FlowEventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<FlowEventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<FlowEventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<FlowEventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<FlowEventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<FlowEventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<FlowEventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<FlowEventHandlers['onRestoreFailed']>((error) => {}, []); const onAppeared = useCallback<FlowEventHandlers['onAppeared']>(() => {}, []); const onError = useCallback<FlowEventHandlers['onError']>((error) => {}, []); const onLoadingProductsFailed = useCallback<FlowEventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<FlowEventHandlers['onUrlPress']>((url, openIn) => { adapty.openWebUrl(url, openIn); return false; }, []); const onCustomAction = useCallback<FlowEventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<FlowEventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyFlowView flow={flow} style={styles.container} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onAppeared={onAppeared} onError={onError} onLoadingProductsFailed={onLoadingProductsFailed} onUrlPress={onUrlPress} onCustomAction={onCustomAction} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> Modal sunum için olay işleyicileri metodunu uygulayın. :::important `setEventHandlers`'ı birden fazla kez çağırmak, sağladığınız işleyicileri geçersiz kılar; bu işlemler hem varsayılan hem de daha önce ayarlanmış işleyicilerin yerini alır. ::: ```javascript showLineNumbers title="React Native (TSX)" const view = await createFlowView(flow); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; }, onAndroidSystemBack() { return true; }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type !== 'user_cancelled'; }, onPurchaseStarted(product) { /***/}, onPurchaseFailed(error, product) { /***/ }, onRestoreCompleted(profile) { /***/ }, onRestoreFailed(error) { /***/ }, onProductSelected(productId) { /***/}, onError(error) { /***/ }, onLoadingProductsFailed(error) { /***/ }, onUrlPress(url, openIn) { adapty.openWebUrl(url, openIn); return false; // Keep flow open }, onAppeared() { /***/ }, onDisappeared() { /***/ }, onWebPaymentNavigationFinished() { /***/ }, }); ``` </TabItem> </Tabs> <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onCloseButtonPress { //Record the event } // onAndroidSystemBack { //Record the event } // onUrlPress { "url": "https://example.com/terms" } // onCustomAction { "actionId": "login" } // onProductSelected { "productId": "premium_monthly" } // onPurchaseStarted { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseCompleted - Success { "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseCompleted - Cancelled { "purchaseResult": { "type": "user_cancelled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseFailed { "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onRestoreCompleted { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } // onRestoreFailed { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } // onError { "error": { "code": "rendering_failed", "message": "Failed to render flow interface", "details": { "underlyingError": "Invalid flow configuration" } } } // onLoadingProductsFailed { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } // onAppeared { //Record the event } // onDisappeared { //Record the event } // onWebPaymentNavigationFinished { //Record the event } ``` </Details> İhtiyacınız olan olay işleyicilerini kaydedebilir, ihtiyacınız olmayanları atlayabilirsiniz. Bu durumda, kullanılmayan olay dinleyicileri oluşturulmaz. Zorunlu olay işleyicisi yoktur. Olay işleyicileri bir boolean döndürür. `true` döndürülürse, görüntüleme süreci tamamlanmış sayılır; böylece flow ekranı kapanır ve bu view için olay dinleyicileri kaldırılır. Bazı olay işleyicilerinin, gerekirse geçersiz kılabileceğiniz bir varsayılan davranışı vardır: - `onCloseButtonPress`: kapatma butonuna basıldığında flow'u kapatır. - `onUrlPress`: tıklanan URL'yi açar ve flow'u açık tutar. - `onAndroidSystemBack` (yalnızca modal sunum için): **Back** butonuna basıldığında flow'u açık tutar. Kapatmak için `true` döndürün. - `onRestoreCompleted`: başarılı bir geri yüklemeden sonra flow'u açık tutar. Kapatmak için `true` döndürün. - `onPurchaseCompleted`: bir satın alma tamamlandıktan sonra flow'u açık tutar. Kapatmak için `true` döndürün. - `onError`: render başarısız olursa flow'u kapatır. ### Olay işleyicileri \{#event-handlers\} | Olay işleyici | Açıklama | |:---|:---| | **onCustomAction** | Bir kullanıcı özel bir eylem gerçekleştirdiğinde, örneğin bir [özel butona](paywall-buttons) tıkladığında çağrılır. | | **onUrlPress** | Bir kullanıcı flow'unuzdaki bir URL'ye tıkladığında çağrılır. | | **onAndroidSystemBack** | Yalnızca modal sunum: Bir kullanıcı Android sistem **Back** butonuna dokunduğunda çağrılır. | | **onCloseButtonPress** | Kapatma butonu görünürken bir kullanıcı ona dokunduğunda çağrılır. Bu işleyicide flow ekranını kapatmanız önerilir. | | **onPurchaseCompleted** | Satın alma tamamlandığında çağrılır; ister başarılı, ister kullanıcı tarafından iptal edilmiş, ister onay bekliyor olsun. Başarılı bir satın alma durumunda güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı iptalleri ve bekleyen ödemeler (örneğin ebeveyn onayı gerektiğinde), `onPurchaseFailed` değil, bu olayı tetikler. | | **onPurchaseStarted** | Bir kullanıcı satın alma sürecini başlatmak için "Purchase" eylem butonuna dokunduğunda çağrılır. | | **onPurchaseFailed** | Bir satın alma hatalar nedeniyle başarısız olduğunda çağrılır (örneğin ödeme kısıtlamaları, geçersiz ürünler, ağ hataları, işlem doğrulama hataları). Bunun yerine `onPurchaseCompleted`'ı tetikleyen kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz. | | **onRestoreStarted** | Bir kullanıcı satın alma geri yükleme sürecini başlattığında çağrılır. | | **onRestoreCompleted** | Satın alma geri yükleme başarılı olduğunda çağrılır ve güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı gerekli `accessLevel`'a sahipse ekranı kapatmanız önerilir. Nasıl kontrol edileceğini öğrenmek için [Abonelik durumu](react-native-listen-subscription-changes) konusuna bakın. | | **onRestoreFailed** | Geri yükleme süreci başarısız olduğunda çağrılır ve `AdaptyError` sağlar. | | **onProductSelected** | Flow view'indeki herhangi bir ürün seçildiğinde çağrılır; böylece kullanıcının satın almadan önce ne seçtiğini izleyebilirsiniz. | | **onError** | View render'ı sırasında bir hata oluştuğunda çağrılır ve `AdaptyError` sağlar. Bu tür hatalar oluşmamalıdır; bir tanesiyle karşılaşırsanız lütfen bize bildirin. | | **onLoadingProductsFailed** | Ürün yükleme başarısız olduğunda çağrılır ve `AdaptyError` sağlar. View oluştururken `prefetchProducts: true` ayarlamadıysanız, AdaptyUI gerekli nesneleri sunucudan kendisi getirir. | | **onAppeared** | Flow kullanıcıya görüntülendiğinde çağrılır. iOS'ta ayrıca, bir kullanıcı bir flow içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve uygulama içi tarayıcıda bir web paywall açıldığında çağrılır. | | **onDisappeared** | Yalnızca modal sunum: Flow kullanıcı tarafından kapatıldığında çağrılır. iOS'ta ayrıca, bir flow'dan uygulama içi tarayıcıda açılan bir [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda çağrılır. | | **onWebPaymentNavigationFinished** | Satın alma için bir [web paywall](web-paywall) açma girişiminden sonra çağrılır; ister başarılı ister başarısız olsun. | | **onAnalytics** | Bir flow'dan gelen özel analiz olayları için ayrılmıştır. Flow'lar bunları henüz kodunuza yaymaz, bu yüzden uygulamanıza gerek yoktur. | | **onRequestAppReview** | Bir flow'dan gelen uygulama değerlendirme istekleri için ayrılmıştır. Flow'lar henüz uygulama değerlendirme isteği tetiklemez, bu yüzden uygulamanıza gerek yoktur. | | **onRequestPermission** | Bir flow'dan gelen sistem izni istekleri (push bildirimleri veya kamera erişimi gibi) için ayrılmıştır. Flow'lar henüz izin isteği tetiklemez, bu yüzden uygulamanıza gerek yoktur. | | **onObserverPurchaseInitiated** | Yalnızca gözlemci modu: Bir kullanıcı bir flow'da satın alma butonuna dokunduğunda çağrılır. Adapty satın almayı yapmaz — onu kendi satın alma kodunuzla gerçekleştirin, ardından işlemi Adapty'ye bildirin. Aşağıdaki [Gözlemci modunda satın almaları yönetme](#handle-purchases-in-observer-mode) bölümüne bakın. | | **onObserverRestoreInitiated** | Yalnızca gözlemci modu: Bir kullanıcı bir flow'da geri yükleme butonuna dokunduğunda çağrılır. Adapty geri yükleme yapmaz — onu kendiniz gerçekleştirin, ardından geri yüklenen işlemleri bildirin. Aşağıdaki [Gözlemci modunda satın almaları yönetme](#handle-purchases-in-observer-mode) bölümüne bakın. | ### Gözlemci modunda satın almaları yönetme \{#handle-purchases-in-observer-mode\} SDK'yı [Gözlemci modunda](implement-observer-mode-react-native) (`observerMode: true`) etkinleştirdiyseniz ve Adapty tarafından render edilen bir flow sunarsanız, SDK satın almaları sizin için yapmaz. Bir kullanıcı satın alma veya geri yükleme butonuna dokunduğunda, SDK bunun yerine `onObserverPurchaseInitiated` veya `onObserverRestoreInitiated` çağırır. Satın almayı veya geri yüklemeyi kendi kodunuzla gerçekleştirin, flow'un yükleme göstergesini sağlanan callback'lerle yönetin ve ardından işlemi Adapty'ye [bildirin](report-transactions-observer-mode-react-native). ```typescript showLineNumbers const unsubscribe = view.setEventHandlers({ onObserverPurchaseInitiated(product, onStartPurchase, onFinishPurchase) { onStartPurchase(); // show the flow's loading indicator myPurchaseApi(product.vendorProductId) .then((transactionId) => adapty.reportTransaction(transactionId)) .finally(() => onFinishPurchase()); // hide the loading indicator return false; // keep the flow open; dismiss it yourself after success }, onObserverRestoreInitiated(onStartRestore, onFinishRestore) { onStartRestore(); myRestoreApi() .finally(() => onFinishRestore()); return false; }, }); ``` </SDKv4> <SDKv3> :::important Bu rehber; satın almalar, geri yüklemeler, ürün seçimi ve paywall render işlemleri için olay yönetimini kapsar. Ayrıca buton yönetimini de (paywall'ı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton eylemlerini yönetme rehberimize](react-native-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılan paywall'lar, satın alma yapmak ve geri yüklemek için ekstra koda ihtiyaç duymaz. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamalarını (kapatma butonları, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın almayla ilgili eylemlere ait bildirimleri içerir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin. :::warning Bu rehber yalnızca **yeni Paywall Builder paywall'ları** içindir; bunlar Adapty SDK v3.0 veya sonrasını gerektirir. ::: Mobil uygulamanızda paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için olay işleyicilerini uygulayın: <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> React bileşeni için olayları, `AdaptyPaywallView` bileşenindeki tekil olay işleyici prop'ları aracılığıyla yönetirsiniz: ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []); const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []); const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []); const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onPaywallShown={onPaywallShown} onRenderingFailed={onRenderingFailed} onLoadingProductsFailed={onLoadingProductsFailed} onUrlPress={onUrlPress} onCustomAction={onCustomAction} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal sunum"> Modal sunum için olay işleyicileri metodunu uygulayın. :::important `setEventHandlers`'ı birden çok kez çağırmak, sağladığınız işleyicileri geçersiz kılar; söz konusu belirli olaylar için hem varsayılan hem de önceden ayarlanmış işleyicilerin yerini alır. ::: ```javascript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; }, onAndroidSystemBack() { return true; }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type !== 'user_cancelled'; }, onPurchaseStarted(product) { /***/}, onPurchaseFailed(error) { /***/ }, onRestoreCompleted(profile) { /***/ }, onRestoreFailed(error) { /***/ }, onProductSelected(productId) { /***/}, onRenderingFailed(error) { /***/ }, onLoadingProductsFailed(error) { /***/ }, onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, onPaywallShown() { /***/ }, onPaywallClosed() { /***/ }, onWebPaymentNavigationFinished() { /***/ }, }); ``` </TabItem> </Tabs> <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onCloseButtonPress { //Record the event } // onAndroidSystemBack { //Record the event } // onUrlPress { "url": "https://example.com/terms" } // onCustomAction { "actionId": "login" } // onProductSelected { "productId": "premium_monthly" } // onPurchaseStarted { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseCompleted - Success { "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseCompleted - Cancelled { "purchaseResult": { "type": "user_cancelled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onPurchaseFailed { "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "price": { "amount": 9.99, "currencyCode": "USD", "currencySymbol": "$", "localizedString": "$9.99" } } } // onRestoreCompleted { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } // onRestoreFailed { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } // onRenderingFailed { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } // onLoadingProductsFailed { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } // onPaywallShown { //Record the event } // onPaywallClosed { //Record the event } // onWebPaymentNavigationFinished { //Record the event } ``` </Details> İhtiyacınız olan olay işleyicilerini kaydedebilir, ihtiyacınız olmayanları atlayabilirsiniz. Bu durumda, kullanılmayan olay dinleyicileri oluşturulmaz. Zorunlu olay işleyicisi yoktur. Olay işleyicileri bir boolean döndürür. `true` döndürülürse, görüntüleme süreci tamamlanmış sayılır; böylece paywall ekranı kapanır ve bu view için olay dinleyicileri kaldırılır. Bazı olay işleyicilerinin, gerekirse geçersiz kılabileceğiniz bir varsayılan davranışı vardır: - `onCloseButtonPress`: kapatma butonuna basıldığında paywall'ı kapatır. - `onUrlPress`: tıklanan URL'yi açar ve paywall'ı açık tutar. - `onAndroidSystemBack` (yalnızca modal sunum için): **Back** butonuna basıldığında paywall'ı kapatır. - `onRestoreCompleted`: başarılı geri yüklemeden sonra paywall'ı kapatır. - `onPurchaseCompleted`: kullanıcı iptal etmediği sürece paywall'ı kapatır. - `onRenderingFailed`: render başarısız olursa paywall'ı kapatır. ### Olay işleyicileri \{#event-handlers\} | Olay işleyici | Açıklama | |:---|:---| | **onCustomAction** | Bir kullanıcı özel bir eylem gerçekleştirdiğinde, örneğin bir [özel butona](paywall-buttons) tıkladığında çağrılır. | | **onUrlPress** | Bir kullanıcı paywall'ınızdaki bir URL'ye tıkladığında çağrılır. | | **onAndroidSystemBack** | Yalnızca modal sunum: Bir kullanıcı Android sistem **Back** butonuna dokunduğunda çağrılır. | | **onCloseButtonPress** | Kapatma butonu görünürken bir kullanıcı ona dokunduğunda çağrılır. Bu işleyicide paywall ekranını kapatmanız önerilir. | | **onPurchaseCompleted** | Satın alma tamamlandığında çağrılır; ister başarılı, ister kullanıcı tarafından iptal edilmiş, ister onay bekliyor olsun. Başarılı bir satın alma durumunda güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı iptalleri ve bekleyen ödemeler (örneğin ebeveyn onayı gerektiğinde), `onPurchaseFailed` değil, bu olayı tetikler. | | **onPurchaseStarted** | Bir kullanıcı satın alma sürecini başlatmak için "Purchase" eylem butonuna dokunduğunda çağrılır. | | **onPurchaseFailed** | Bir satın alma hatalar nedeniyle başarısız olduğunda çağrılır (örneğin ödeme kısıtlamaları, geçersiz ürünler, ağ hataları, işlem doğrulama hataları). Bunun yerine `onPurchaseCompleted`'ı tetikleyen kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz. | | **onRestoreStarted** | Bir kullanıcı satın alma geri yükleme sürecini başlattığında çağrılır. | | **onRestoreCompleted** | Satın alma geri yükleme başarılı olduğunda çağrılır ve güncellenmiş bir `AdaptyProfile` sağlar. Kullanıcı gerekli `accessLevel`'a sahipse ekranı kapatmanız önerilir. Nasıl kontrol edileceğini öğrenmek için [Abonelik durumu](react-native-listen-subscription-changes) konusuna bakın. | | **onRestoreFailed** | Geri yükleme süreci başarısız olduğunda çağrılır ve `AdaptyError` sağlar. | | **onProductSelected** | Paywall view'indeki herhangi bir ürün seçildiğinde çağrılır; böylece kullanıcının satın almadan önce ne seçtiğini izleyebilirsiniz. | | **onRenderingFailed** | View render'ı sırasında bir hata oluştuğunda çağrılır ve `AdaptyError` sağlar. Bu tür hatalar oluşmamalıdır; bir tanesiyle karşılaşırsanız lütfen bize bildirin. | | **onLoadingProductsFailed** | Ürün yükleme başarısız olduğunda çağrılır ve `AdaptyError` sağlar. View oluştururken `prefetchProducts: true` ayarlamadıysanız, AdaptyUI gerekli nesneleri sunucudan kendisi getirir. | | **onPaywallShown** | Paywall kullanıcıya görüntülendiğinde çağrılır. iOS'ta ayrıca, bir kullanıcı bir paywall içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve uygulama içi tarayıcıda bir web paywall açıldığında çağrılır. | | **onPaywallClosed** | Yalnızca modal sunum: Paywall kullanıcı tarafından kapatıldığında çağrılır. iOS'ta ayrıca, bir paywall'dan uygulama içi tarayıcıda açılan bir [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda çağrılır. | | **onWebPaymentNavigationFinished** | Satın alma için bir [web paywall](web-paywall) açma girişiminden sonra çağrılır; ister başarılı ister başarısız olsun. | </SDKv3> --- # File: react-native-use-fallback-paywalls-expo --- --- title: "Bir Expo projesinde yedek paywall'ları kullanma" description: "react-native-adapty yapılandırma eklentisi aracılığıyla bir Expo React Native projesinde yedek paywall'ları yapılandırın." --- :::important Bu kılavuz **Expo projeleri** için geçerlidir. **Saf React Native (Expo olmayan)** kullanıyorsanız, bunun yerine [saf React Native yedek paywall kılavuzunu](react-native-use-fallback-paywalls-pure) izleyin. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: Adapty SDK, yedek dosyasını **native** bundle'dan okur; iOS'ta `.app` paketinin içindeki bir kaynak dosyası, Android'de ise `android/app/src/main/assets/` altındaki bir girdi olarak yer alır. Expo projelerinde `npx expo prebuild --clean` komutu her çalıştırıldığında bu dizinleri yeniden oluşturur, bu yüzden dosyaları manuel olarak ekleyemezsiniz. `react-native-adapty` config plugin, dosyayı native bundle'a sizin yerinize bağlar. :::tip Tam çalışan bir örnek kurulum [`FocusJournalExpo` örnek uygulamasında](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) mevcuttur. ::: ## Yapılandırma \{#configuration\} 1. Yedek JSON dosyalarını projenizde herhangi bir yere yerleştirin — genellikle diğer asset'lerin yanına: ``` <your-project>/ └── assets/ ├── ios_fallback.json └── android_fallback.json ``` 2. `app.json` (veya `app.config.js`) içindeki `react-native-adapty` girdisine `fallbackFile` seçeneğini ekleyin. Her platform anahtarı isteğe bağlıdır — yalnızca ihtiyaç duyduğunuz platformları bağlayın: ```json title="app.json" { "expo": { "plugins": [ [ "react-native-adapty", { "fallbackFile": { "ios": "./assets/ios_fallback.json", "android": "./assets/android_fallback.json" } } ] ] } } ``` :::note Adapty her platform için farklı bir yedek JSON dışa aktarır — iOS'ta Apple ürün ID'leri, Android'de Google Play ürün ID'leri. Her platformu kendi dosyasına yönlendirin. ::: 3. Yerel projeleri yeniden oluşturun: ```sh title="Shell" npx expo prebuild ``` Eklenti, iOS dosyasını Xcode projesinin paket kaynaklarına ekler ve Android dosyasını `android/app/src/main/assets/` içine kopyalar. Prebuild çıktısı şuna benzer satırlar içerir: ``` [react-native-adapty] Registered ios_fallback.json as iOS bundle resource [react-native-adapty] Copied android_fallback.json to android assets/ ``` 4. Dosyayı çalışma zamanında SDK'ya kaydedin: ```typescript showLineNumbers title="App.tsx" import { adapty } from 'react-native-adapty'; await adapty.activate('PUBLIC_SDK_KEY'); await adapty.setFallback({ ios: { fileName: 'ios_fallback.json' }, android: { relativeAssetPath: 'android_fallback.json' }, }); ``` `setFallback`'e geçirilen dosya adları, `fallbackFile` altında yapılandırılan dosyaların temel adlarıyla (basename) eşleşmelidir. :::important `setFallback`, SDK hedef flow'u, paywall'ı veya onboarding'i getirmeden önce çalışmalıdır. ::: ## Doğrulama \{#verification\} `npx expo prebuild` çalıştırdıktan sonra her iki platformu da kontrol edin: - **Android**: `android/app/src/main/assets/` dizininin içeriğini listeleyin. `fallbackFile.android` altında yapılandırılan dosya burada bulunmalı, yalnızca iOS'a ait dosya adı ise burada görünmemelidir. - **iOS**: `ios/<ProjectName>.xcodeproj/project.pbxproj` dosyasında iOS dosya adını aratın. `PBXFileReference`, `Resources` grubu ve `PBXResourcesBuildPhase` içinde görünmelidir. Yalnızca Android'e ait dosya adı ise `project.pbxproj` içinde yer almamalıdır. --- # File: react-native-use-fallback-paywalls-pure --- --- title: "Saf bir React Native projesinde yedek paywall'ları kullanma" description: "Saf bir React Native (Expo olmayan) projesinde yedek paywall'ları yapılandırın." --- :::important Bu kılavuz **saf React Native (Expo olmayan) projeleri** için geçerlidir. **Expo** kullanıyorsanız, bunun yerine [Expo yedek paywall kılavuzunu](react-native-use-fallback-paywalls-expo) takip edin. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} ### Android 1. Yedek yapılandırma dosyasını uygulamanıza ekleyin. Aşağıdaki dizinlerden birini seçin: * **android/app/src/main/assets/** * **android/app/src/main/res/raw/** Not: `res/raw` klasörü özel bir dosya adlandırma kuralı gerektirir (harf ile başlamalı, büyük harf kullanılmamalı, alt çizgi dışında özel karakter bulunmamalı ve isimde boşluk olmamalıdır). 2. `FileLocation` sabitinin `android` özelliğini güncelleyin: * Dosya `assets` dizinindeyse, dizine göre dosyanın göreli yolunu girin. * Dosya `res/raw` dizinindeyse, dosyanın uzantısız adını girin. ### iOS 1. Yedek JSON dosyasını proje paketinize ekleyin: XCode'da **File** menüsünü açın ve **Add Files to "YourProjectName"** seçeneğini belirleyin. 2. Yapılandırma dosyanızın adını `FileLocation` sabitinin `ios` özelliğine geçirin. ## Örnek \{#example\} <Tabs groupId="current-os" queryString> <TabItem value="current" label="Güncel (v3.8+)" default> ```typescript showLineNumbers //after v3.8 const fileLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } } await adapty.setFallback(fileLocation); ``` </TabItem> <TabItem value="old" label="Eski (v3.8 öncesi)"> ```typescript showLineNumbers //Legacy (before v3.8) const paywallsLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } } await adapty.setFallbackPaywalls(paywallsLocation); ``` </TabItem> </Tabs> | Parametre | Açıklama | | :------------------- | :------------------------------------------------------- | | **fileLocation** | Yedek yapılandırma dosyasının konumunu temsil eden nesne. | --- # File: react-native-localizations-and-locale-codes --- --- title: "React Native SDK'da yerelleştirmeleri ve locale kodlarını kullanma" description: "Adapty SDK ile React Native uygulamanızda paywall'ları nasıl yerelleştireceğinizi öğrenin." --- <SDKv4> ## Bu neden önemli \{#why-this-is-important\} Locale kodları, Adapty bir flow için yerelleştirmeyi seçtiğinde ve özel bir paywall için remote config okuduğunuzda devreye girer. Locale kodları karmaşıktır ve platformdan platforma değişebilir, bu yüzden Adapty desteklediği her platformda tek bir dahili standart kullanır. Bu standardı anlamak, bir kullanıcının hangi yerelleştirmeyi aldığını tahmin etmenize yardımcı olur. ## Adapty'de locale kodu standardı \{#locale-code-standard-at-adapty\} Locale kodları için Adapty, hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, tirelerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Locale kodu eşleştirme \{#locale-code-matching\} Adapty bir kullanıcının locale'iyle eşleşen yerelleştirmeyi ararken şunlar olur: 1. Locale dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) tirelerle (`-`) değiştirilir 2. Adapty tam olarak eşleşen locale koduna sahip yerelleştirmeyi arar 3. Eşleşme bulunmazsa, Adapty ilk tireden önceki alt dizeyi alır (`pt-br` için `pt`) ve eşleşen yerelleştirmeyi arar 4. Yine eşleşme bulunmazsa, Adapty varsayılan `en` yerelleştirmesini döndürür Bu şekilde `'pt_BR'`, `pt-BR` ve `pt-br` hepsi aynı yerelleştirmeye çözümlenir. ## Yerelleştirmeleri uygulama \{#implementing-localizations\} SDK v4'te, bir flow getirirken locale kodu geçmezsiniz. - **Flow Builder ve Paywall Builder paywall'ları**: Adapty yerelleştirmeyi cihazdan ve builder'da yapılandırdığınız yerelleştirmelerden otomatik olarak çözümler. Flow'u `createFlowView` ile render edin — locale koduna gerek yoktur. - **Özel (remote config) paywall'lar**: `getFlow`, yapılandırılmış her yerelleştirmeyi `flow.remoteConfigs` içinde döndürür. Her girdide bir `lang` kodu ve bir `data` nesnesi bulunur. Kullanıcıya uyan girdiyi, kendi yedeğinizle birlikte seçin: ```typescript showLineNumbers const flow = await adapty.getFlow('placement_id'); const config = flow.remoteConfigs?.find((c) => c.lang === 'en') ?? flow.remoteConfigs?.[0]; // read your values from config?.data ``` Yukarıdaki locale kodu eşleştirme kuralları, Adapty'nin her remote config'te saklanan `lang` kodlarını nasıl normalleştirdiğini açıklar. </SDKv4> <SDKv3> ## Bu neden önemli \{#why-this-is-important\} Locale kodlarının devreye girdiği birkaç senaryo vardır — örneğin, uygulamanızın mevcut yerelleştirmesi için doğru paywall'ı getirmeye çalışırken. Locale kodları karmaşık olduğundan ve platformdan platforma değişebildiğinden, desteklediğimiz tüm platformlar için dahili bir standart kullanırız. Ancak bu kodlar karmaşık olduğu için, doğru yerelleştirmeyi almak üzere sunucumuza tam olarak ne gönderdiğinizi ve sonrasında ne olduğunu anlamanız gerçekten önemlidir — böylece her zaman beklediğinizi alırsınız. ## Adapty'de locale kodu standardı \{#locale-code-standard-at-adapty\} Locale kodları için Adapty, hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, tirelerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Locale kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan locale kodunu içeren bir çağrı aldığında ve bir paywall'ın ilgili yerelleştirmesini aramaya başladığında şunlar olur: 1. Gelen locale dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) tirelerle (`-`) değiştirilir 2. Ardından tam olarak eşleşen locale koduna sahip yerelleştirmeyi ararız 3. Eşleşme bulunmazsa, ilk tireden önceki alt dizeyi alırız (`pt-br` için `pt`) ve eşleşen yerelleştirmeyi ararız 4. Yine eşleşme bulunmazsa, varsayılan `en` yerelleştirmesini döndürürüz Bu şekilde `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yöntem \{#implementing-localizations-recommended-way\} Yerelleştirmeler hakkında düşünüyorsanız, muhtemelen projenizde yerelleştirilmiş dize dosyalarıyla zaten uğraşıyorsunuzdur. Durum buysa, ilgili yerelleştirmeler için dosyalarınızın her birine, amaçlanan Adapty locale kodunu içeren bir anahtar-değer yerleştirmenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde çıkarın: ```javascript showLineNumbers // 1. Modify your localization files (e.g., using react-i18next) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Extract and use the locale code const MyComponent = () => { const { t } = useTranslation(); const fetchPaywall = async () => { const locale = t('adapty_paywalls_locale'); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; }; ``` Bu şekilde, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği konusunda tam kontrole sahip olduğunuzdan emin olabilirsiniz. ## Yerelleştirmeleri uygulama: diğer yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için locale kodlarını açıkça tanımlamadan benzer (ama aynı olmayan) sonuçlar elde edebilirsiniz. Bu, cihazdan bir locale kodu çıkarmak anlamına gelir; örneğin [`react-native-localize`](https://github.com/zoontek/react-native-localize) aracılığıyla: ```javascript showLineNumbers const fetchPaywall = async () => { // getLocales() returns the user's preferred locales in BCP-47 format (e.g., 'en-US', 'pt-BR') const locale = RNLocalize.getLocales()[0].languageTag; // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; ``` Bu yaklaşımı birkaç nedenden dolayı önermediğimizi unutmayın: 1. iOS'ta tercih edilen diller ve mevcut bölgesel locale aynı değildir. Yerelleştirmenin doğru seçilmesini istiyorsanız, ya Apple'ın çözümleme mantığına güvenmeniz gerekir — ki bu, yerelleştirilmiş dize dosyalarıyla önerilen yaklaşımı kullandığınızda hazır olarak çalışır — ya da onu kendiniz yeniden oluşturmanız gerekir. 2. Cihaz locale'i, Adapty'de yapılandırdığınız hiçbir yerelleştirmeyle eşleşmeyebilir. Bu durumda SDK, ilk alt etiket eşleşmesine veya nihayetinde `en`'e geri döner — ki bu, o kullanıcı için varsayılan yapmak isteyeceğiniz dil olmayabilir. Yine de bu yaklaşımı kullanmaya karar verirseniz — ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun. </SDKv3> --- # File: react-native-web-paywall --- --- title: "Web paywall'ları uygulama" description: "Adapty SDK ile React Native uygulamanızda web paywall'larını nasıl uygulayacağınızı öğrenin." --- :::important Başlamadan önce [kontrol panelinde web paywall'ınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya daha yeni bir sürümünü kurduğunuzdan emin olun. ::: ## Web paywall'ları açma \{#open-web-paywalls\} Kendiniz geliştirdiğiniz bir paywall ile çalışıyorsanız, web paywall'larını SDK metoduyla yönetmeniz gerekir. `.openWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'ı yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya geri döndüğü anı takip eder ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` isteği gönderir. Bu sayede, ödeme başarılı olmuşsa ve erişim hakları güncellenmiş ise abonelik uygulamada neredeyse anında etkinleşir. ```typescript showLineNumbers title="React Native (TSX)" try { await adapty.openWebPaywall(product); } catch (error) { console.warn('Failed to open web paywall:', error); } ``` :::note `openWebPaywall` metodunun iki versiyonu vardır: 1. `openWebPaywall(product)`: paywall'a göre URL oluşturur ve ürün verilerini de URL'lere ekler. 2. `openWebPaywall(paywall)`: paywall'a göre URL oluşturur, ancak ürün verilerini URL'lere eklemez. Adapty paywall'ındaki ürünler web paywall'ındaki ürünlerden farklıysa bunu kullanın. ::: #### Hataları yönetme \{#handle-errors\} | Hata | Açıklama | Önerilen işlem | |-----------------------------------------|---------------------------------------------------------------|-------------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Paywall'da yapılandırılmış bir web satın alma URL'si yok | Paywall'ın Adapty Kontrol Paneli'nde doğru şekilde yapılandırılıp yapılandırılmadığını kontrol edin | | AdaptyError.productWithoutPurchaseUrl | Ürünün web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın | | AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun | | AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler doğru şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimlendirilmiş olduğunu doğrulayın | ## Web paywalllarını uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywalllarını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15'ten itibaren desteklenmektedir. ::: Web paywallları varsayılan olarak harici tarayıcıda açılır. Kesintisiz bir kullanıcı deneyimi sunmak için web paywalllarını uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanızın içinde gösterilir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `openWebPaywall` fonksiyonuna ikinci argüman olarak `WebPresentation.BrowserInApp` değerini geçin: ```typescript showLineNumbers title="React Native (TSX)" try { await adapty.openWebPaywall( product, WebPresentation.BrowserInApp, // default – WebPresentation.BrowserOutApp ); } catch (error) { console.warn('Failed to open web paywall:', error); } ``` --- # File: react-native-troubleshoot-paywall-builder --- --- title: "React Native SDK'da Paywall Builder Sorunlarını Giderme" description: "React Native SDK'da Paywall Builder Sorunlarını Giderme" --- Bu kılavuz, React Native SDK'da Adapty Paywall Builder ile tasarlanan paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Bir paywall yapılandırmasını getirme başarısız oluyor \{#getting-a-paywall-configuration-fails\} **Sorun**: Bir flow veya paywall için view yapılandırmasını getirme başarısız oluyor. **Neden**: Paywall, Paywall Builder'da cihazda gösterim için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin. <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Paywall görüntüleme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntüleme sayısı beklenenin iki katını gösteriyor. **Neden**: Kodunuzda `logShowFlow` (React Native SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz; bu, Paywall Builder veya Flow Builder kullanıyorsanız görüntüleme sayısını ikiye katlar. Bu araçlarla oluşturulmuş flow'lar ve paywall'lar için analizler otomatik olarak izlenir, bu yüzden bu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız, kodunuzda `logShowFlow` (React Native SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder sorunları yaşıyorsunuz. **Çözüm**: Gerekirse [migration kılavuzlarını](react-native-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüştür. --- # File: react-native-quickstart-manual --- --- title: "React Native SDK'da özel paywall'ınızda satın almaları etkinleştirme" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel React Native paywall'larınıza entegre edin." --- Bu rehber, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall uygulamanız üzerinde tam kontrolü elinizde tutarken, Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler. :::important **Bu rehber, özel paywall'lar geliştiren geliştiriciler içindir.** Satın almaları etkinleştirmenin en kolay yolunu istiyorsanız, [Adapty Flow Builder](react-native-quickstart-paywalls)'ı kullanın. Flow Builder ile flow'ları kod gerektirmeyen görsel bir editörde oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve farklı tasarımları uygulamanızı yeniden yayınlamadan test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlayın \{#set-up-products\} Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de paywalllar, ürünleri almanın tek yoludur; ancak bu tasarım sayesinde uygulama kodunuza dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. - [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'si ile bunları talep edersiniz. Bu, A/B testleri yapmanızı ve farklı kullanıcılara farklı paywalllar göstermenizi kolaylaştırır. Özel paywall üzerinde çalışıyor olsanız bile bu kavramları anladığınızdan emin olun. Temel olarak bunlar, uygulamanızda sattığınız ürünleri yönetme yönteminizdir. Özel paywallinizi uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu yapılandırma, ürünlerinizi almanıza olanak tanır. Kontrol panelinde ne yapmanız gerektiğini anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetin \{#manage-users\} Kendi tarafınızda backend kimlik doğrulaması ile veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve kimliği doğrulanmış kullanıcıları farklı şekilde ele alır. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik doğrulama hızlı başlangıç kılavuzunu](react-native-quickstart-identify) okuyun. ## Adım 1. Ürünleri getirin \{#step-1-get-products\} Özel paywall'ınız için ürünleri getirmek üzere şunları yapmanız gerekir: 1. `getFlow` metoduna [placement](placements) ID'sini geçirerek `flow` nesnesini alın. 2. `getPaywallProducts` metodunu kullanarak bu flow için ürünler dizisini alın. ```typescript showLineNumbers async function loadPaywall() { try { const flow: AdaptyFlow = await adapty.getFlow('YOUR_PLACEMENT_ID'); const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts(flow); // Use products to build your custom paywall UI } catch (error) { // Handle the error } } ``` ## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\} Kullanıcı özel paywallınızdaki bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```typescript showLineNumbers async function purchaseProduct(product: AdaptyPaywallProduct) { try { const purchaseResult: AdaptyPurchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': // Purchase successful, profile updated break; case 'user_cancelled': // User canceled the purchase break; case 'pending': // Purchase is pending (e.g., user will pay offline with cash) break; } } catch (error) { // Handle the error } } ``` ## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik sunan tüm uygulamaların kullanıcılara satın almalarını geri yükleyebilecekleri bir yol sağlamasını zorunlu kılar. Kullanıcı geri yükle düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişlerini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```typescript showLineNumbers async function restorePurchases() { try { const profile: AdaptyProfile = await adapty.restorePurchases(); // Restore successful, profile updated } catch (error) { // Handle the error } } ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywallınız uygulamada gösterilmeye hazır. [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da satın almalarınızı test ederek paywall üzerinden bir test satın almasını tamamlayabildiğinizden emin olun. Bunun üretime hazır bir uygulamada nasıl çalıştığını görmek için örnek uygulamamızdaki [CustomPurchaseScreen.tsx](https://github.com/adaptyteam/AdaptySDK-React-Native/blob/master/examples/ExpoGoWebMock/src/CustomPurchaseScreen.tsx) dosyasına göz atın; bu dosya, uygun hata işleme, yükleme durumları ve UI durum yönetimiyle satın alma işlemini göstermektedir. Ardından, paywallı gösterip göstermeyeceğinizi veya ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın almalarını tamamlayıp tamamlamadığını kontrol edin](react-native-check-subscription-status). --- # File: fetch-paywalls-and-products-react-native --- --- title: "React Native SDK'da remote config paywall'ları için paywall'ları ve ürünleri getirme" description: "Kullanıcı para kazanımını artırmak için Adapty React Native SDK'da paywall'ları ve ürünleri getirin." --- <SDKv4> Remote config ve özel paywall'ları sergilemeden önce, onlar hakkındaki bilgileri getirmeniz gerekir. Lütfen bu konunun remote config ve özel paywall'lara atıfta bulunduğunu unutmayın. **Flow Builder** veya **Paywall Builder**'da özelleştirilen flow'ları veya paywall'ları getirmeyle ilgili yönergeler için [Flow Builder flow'larını ve Paywall Builder paywall'larını ve yapılandırmalarını getirme](react-native-get-pb-paywalls) bölümüne başvurun. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda flow'ları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri ona dahil edin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow'unuzu veya paywall'ınızı placement'a dahil edin](create-placement). 4. Mobil uygulamanızda [Adapty SDK'yı yükleyin](sdk-installation-reactnative). </details> ## Flow bilgilerini getirme \{#fetch-flow-information\} Adapty'de bir [ürün](product), hem App Store hem de Google Play'deki ürünlerin bir kombinasyonu olarak işlev görür. Bu platformlar arası ürünler flow'lara ve paywall'lara entegre edilir; böylece onları belirli mobil uygulama placement'larında sergileyebilirsiniz. Ürünleri görüntülemek için, `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir. :::important **Ürün ID'lerini koda gömmeyin (hardcode).** Koda gömmeniz gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırılır, bu yüzden ürünlerin sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak yönetmelidir—bir flow bugün iki, yarın üç ürün döndürürse, kod değişikliği olmadan hepsini gösterin. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlow(id); // the requested flow } catch (error) { // handle the error } ``` | Parametre | Zorunlu | Açıklama | |-------------------|--------|-----------| | **placementId** | gerekli | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nizde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu varyantı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın istikrarsız internetle uğraştığını düşünüyorsanız, önbelleğe alınmış veriler varsa onları döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar mutlak en son verileri alamayabilir, ancak internet bağlantıları ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Uygulamayı yeniden başlattığınızda önbelleğin bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, flow'ları ve paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](react-native-use-fallback-paywalls) . Ayrıca flow'ları ve paywall'ları daha hızlı getirmek için CDN'i ve CDN erişilemez olduğunda bağımsız bir yedek sunucuyu kullanırız. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman flow'larınızın en son sürümünü almanızı garanti etmek için tasarlanmıştır.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>Bu değer, bu metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa, önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun, işlem alt katmanda farklı isteklerden oluşabileceği için `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.</p> | :::note v4'te `getFlow` artık `locale` parametresi almaz. Özel paywall'lar için, mevcut tüm locale'ler flow'un remote config'inde (`flow.remoteConfigs`) döndürülür—kullanıcının cihazına veya uygulama ayarına uyanı seçin. ::: Ürün ID'lerini koda gömmeyin (hardcode)! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz denemeler gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları yönettiğinden emin olun. Örneğin, başlangıçta 2 ürün getirirseniz, uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün getirirseniz, uygulamanız herhangi bir kod değişikliği gerektirmeden 3'ünü de göstermelidir. Koda gömmeniz gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Placement'ı, tanımlayıcıları (`id`, `variationId`), adı, paywall varyasyonlarını (`paywalls`) ve bir `remoteConfigs` dizisini (yapılandırılmış her locale için bir girdi) içeren bir `AdaptyFlow` nesnesi. Flow için ürünleri getirmek üzere `getPaywallProducts(flow)` çağırın. | ## Ürünleri getirme \{#fetch-products\} Flow'a sahip olduğunuzda, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```typescript showLineNumbers try { // ...flow const products = await adapty.getPaywallProducts(flow); // the requested products list } catch (error) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer birkaç özelliği içeren [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) nesnesindeki bu özelliklere erişmeniz gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler için bağlantılı belgeye başvurun. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın locale'inden ziyade kullanıcıların seçtiği mağaza ülkesine dayandığını unutmayın. | | **Price** | Fiyatın yerelleştirilmiş bir sürümünü görüntülemek için `product.price?.localizedString` kullanın. Bu yerelleştirme, cihazın locale bilgisine dayanır. Fiyata `product.price?.amount` kullanarak bir sayı olarak da erişebilirsiniz. Değer yerel para biriminde sağlanır. İlgili para birimi sembolünü almak için `product.price?.currencySymbol` kullanın. | | **Subscription Period** | Süreyi (örneğin hafta, ay, yıl vb.) görüntülemek için `product.subscription?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme, cihazın locale'ine dayanır. Abonelik süresini programatik olarak getirmek için `product.subscription?.subscriptionPeriod` kullanın. Oradan, uzunluğu almak için `unit` özelliğine erişebilirsiniz (yani 'day', 'week', 'month', 'year' veya 'unknown'). `numberOfUnits` değeri size süre birimi sayısını verir. Örneğin, üç aylık bir abonelik için, unit özelliğinde `'month'` ve numberOfUnits özelliğinde `3` görürsünüz. | | **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerdiğini gösteren bir rozet veya başka bir gösterge görüntülemek için, `product.subscription?.offer?.phases` özelliğine göz atın. Bu, en fazla iki indirim aşaması içerebilen bir listedir: ücretsiz deneme aşaması ve başlangıç fiyatı aşaması. Her aşama nesnesinde şu yararlı özellikler bulunur:<br/>• `paymentMode`: `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` ve `'unknown'` değerlerine sahip bir dize. Ücretsiz denemeler `'free_trial'` türünde olur.<br/>• `price`: Bir sayı olarak indirimli fiyat. Ücretsiz denemeler için burada `0` arayın.<br/>• `localizedNumberOfPeriods`: Teklifin uzunluğunu açıklayan, cihazın locale'i kullanılarak yerelleştirilmiş bir dize. Örneğin, üç günlük bir deneme teklifi bu alanda `'3 days'` gösterir.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarını bu özellikle ayrı ayrı alabilirsiniz. Teklifler için önceki bölümde açıklandığı şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının locale'i için biçimlendirilmiş bir indirim abonelik süresi. | ## Varsayılan kitle flow'uyla flow getirmeyi hızlandırma \{#speed-up-flow-fetching-with-default-audience-flow\} Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve placement'ınız olduğu ve kullanıcılarınızın zayıf internet bağlantısı olduğu durumlarda, bir flow'u getirmek istediğinizden daha uzun sürebilir. Bu tür durumlarda, hiçbir şey göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın flow'unu **All Users** kitlesi için getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgilerini getirme](fetch-paywalls-and-products-react-native#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi flow'u `getFlow` metoduyla getirmek olduğunu anlamak çok önemlidir. :::warning `getFlow` kullanmanızı neden öneriyoruz `getFlowForDefaultAudience` metodu birkaç önemli dezavantajla birlikte gelir: - **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı flow'lar göstermeniz gerekiyorsa, zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmemiş flow'larla sorun yaşayabileceğini kabul etmeniz gerekir. - **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görür; bu da kişiselleştirilmiş hedeflemeyi kaybettiğiniz anlamına gelir (ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı olanlar dahil). Daha hızlı flow getirmeden yararlanmak için bu dezavantajları kabul etmeye istekliyseniz, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products-react-native#fetch-flow-information) açıklanan `getFlow`'a bağlı kalın. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlowForDefaultAudience(id); // the requested flow } catch (error) { // handle the error } ``` | Parametre | Zorunlu | Açıklama | |---------|--------|-----------| | **placementId** | gerekli | [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nizde bir placement oluştururken belirttiğiniz değerdir. | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, verileri sunucudan yüklemeye çalışır ve başarısızlık durumunda önbelleğe alınmış verileri döndürür. Bu varyantı öneririz çünkü kullanıcılarınızın her zaman en güncel verileri almasını sağlar.</p><p></p><p>Ancak kullanıcılarınızın istikrarsız internetle uğraştığını düşünüyorsanız, önbelleğe alınmış veriler varsa onları döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar mutlak en son verileri alamayabilir, ancak internet bağlantıları ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu yüzden ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Uygulamayı yeniden başlattığınızda önbelleğin bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla temizlendiğini unutmayın.</p> | </SDKv4> <SDKv3> Remote config ve özel paywall'ları sergilemeden önce, onlar hakkındaki bilgileri getirmeniz gerekir. Lütfen bu konunun remote config ve özel paywall'lara atıfta bulunduğunu unutmayın. Paywall Builder ile özelleştirilen paywall'lar için paywall getirmeyle ilgili yönergeler için [Paywall Builder paywall'larını ve yapılandırmalarını getirme](react-native-get-pb-paywalls) bölümüne başvurun. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywall'ları ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri paywall'ınıza dahil edin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı placement'a dahil edin](create-placement). 4. Mobil uygulamanızda [Adapty SDK'yı yükleyin](sdk-installation-reactnative). </details> ## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'deki ürünlerin bir kombinasyonudur. Bu çapraz platform ürünler paywallara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri görüntüleyebilmek için `getPaywall` metoduyla [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini doğrudan koda yazmayın.** Doğrudan koda yazmanız gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak yönetmelidir; bugün iki ürün döndüren bir paywall yarın üç ürün döndürüyorsa, kod değişikliği yapmadan hepsini göstermelisiniz. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywall(id, locale); // the requested paywall } catch (error) { // handle the error } ``` | Parametre | Zorunluluk | Açıklama | |-------------------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel kod hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel kodlar](react-native-localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veri mevcutsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en son verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](react-native-use-fallback-paywalls). Paywallları daha hızlı çekmek için CDN ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu da kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garantilemek için tasarlanmıştır.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Ürün ID'lerini doğrudan koda yazmayın! Paywalllar uzaktan yapılandırıldığından mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları yönettiğinden emin olun. Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün alırsanız uygulamanız herhangi bir kod değişikliği gerektirmeden 3 ürünü de göstermelidir. Doğrudan koda yazmanız gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'leri listesi, paywall tanımlayıcısı, remote config ve diğer birkaç özelliği içeren [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywall'ı aldıktan sonra ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```typescript showLineNumbers try { // ...paywall const products = await adapty.getPaywallProducts(paywall); // the requested products list } catch (error) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Şunları içeren [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) nesnelerinin listesi: ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik uzunluğu ve diğer birkaç özellik. | Kendi paywall tasarımınızı uygularken, muhtemelen [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) nesnesindeki bu özelliklere erişmeniz gerekecek. Aşağıda en yaygın kullanılan özellikler gösterilmiştir, ancak mevcut tüm özelliklerle ilgili tam ayrıntılar için bağlantılı belgeye bakın. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Ürünün başlığını görüntülemek için `product.localizedTitle` kullanın. Yerelleştirmenin, cihazın locale'inden ziyade kullanıcıların seçtiği mağaza ülkesine dayandığını unutmayın. | | **Price** | Fiyatın yerelleştirilmiş bir sürümünü görüntülemek için `product.price?.localizedString` kullanın. Bu yerelleştirme, cihazın locale bilgisine dayanır. Fiyata `product.price?.amount` kullanarak bir sayı olarak da erişebilirsiniz. Değer yerel para biriminde sağlanır. İlgili para birimi sembolünü almak için `product.price?.currencySymbol` kullanın. | | **Subscription Period** | Süreyi (örneğin hafta, ay, yıl vb.) görüntülemek için `product.subscription?.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme, cihazın locale'ine dayanır. Abonelik süresini programatik olarak getirmek için `product.subscription?.subscriptionPeriod` kullanın. Oradan, uzunluğu almak için `unit` özelliğine erişebilirsiniz (yani 'day', 'week', 'month', 'year' veya 'unknown'). `numberOfUnits` değeri size süre birimi sayısını verir. Örneğin, üç aylık bir abonelik için, unit özelliğinde `'month'` ve numberOfUnits özelliğinde `3` görürsünüz. | | **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerdiğini gösteren bir rozet veya başka bir gösterge görüntülemek için, `product.subscription?.offer?.phases` özelliğine göz atın. Bu, en fazla iki indirim aşaması içerebilen bir listedir: ücretsiz deneme aşaması ve başlangıç fiyatı aşaması. Her aşama nesnesinde şu yararlı özellikler bulunur:<br/>• `paymentMode`: `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` ve `'unknown'` değerlerine sahip bir dize. Ücretsiz denemeler `'free_trial'` türünde olur.<br/>• `price`: Bir sayı olarak indirimli fiyat. Ücretsiz denemeler için burada `0` arayın.<br/>• `localizedNumberOfPeriods`: Teklifin uzunluğunu açıklayan, cihazın locale'i kullanılarak yerelleştirilmiş bir dize. Örneğin, üç günlük bir deneme teklifi bu alanda `'3 days'` gösterir.<br/>• `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarını bu özellikle ayrı ayrı alabilirsiniz. Teklifler için önceki bölümde açıklandığı şekilde çalışır.<br/>• `localizedSubscriptionPeriod`: Kullanıcının locale'i için biçimlendirilmiş bir indirim abonelik süresi. | ## Varsayılan kitle paywall'ıyla paywall çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Normalde paywalllar neredeyse anında çekilir, bu nedenle bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywall'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir paywall çekme işlemi istediğinizden daha uzun sürebilir. Bu durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için paywall'ını çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products-react-native#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metoduyla paywall çekmek olduğunu anlamak önemlidir. :::warning Neden `getPaywall` kullanmanızı öneriyoruz `getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır: - **Potansiyel geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa sorunlarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmeyen paywalllarla karşılaşabileceğini kabul edersiniz. - **Hedefleme kaybı**: Tüm kullanıcılar **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywall'ı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel özelliklerinize göre hedefleme dahil) kaybettiğiniz anlamına gelir. Daha hızlı paywall çekme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, aşağıdaki gibi `getPaywallForDefaultAudience` metodunu kullanın. Aksi takdirde [yukarıda](fetch-paywalls-and-products-react-native#fetch-paywall-information) açıklanan `getPaywall` metoduna bağlı kalın. ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note `getPaywallForDefaultAudience` metodu React Native SDK 2.11.2 sürümünden itibaren kullanılabilir. ::: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel kod hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel kodlar](react-native-localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veri mevcutsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en son verilere ulaşamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.</p> | </SDKv3> --- # File: present-remote-config-paywalls-react-native --- --- title: "React Native SDK'da remote config ile tasarlanan paywall'ı render etme" description: "Kullanıcı deneyimini kişiselleştirmek için Adapty React Native SDK'da remote config paywall'larını nasıl sunacağınızı keşfedin." --- <SDKv4> Bir flow'u remote config kullanarak özelleştirdiyseniz, onu kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre uyarlanmış esneklik sunduğundan, neyin dahil edileceği ve flow view'inizin nasıl görüneceği sizin kontrolünüzdedir. Remote config'i getirmek için bir metot sağlıyoruz; böylece remote config ile yapılandırdığınız özel flow'unuzu sergileme özerkliğine sahip olursunuz. ## Flow remote config'ini alın ve sunun \{#get-flow-remote-config-and-present-it\} v4'te bir flow, `remoteConfigs` dizisinde yapılandırılmış her dil için bir `AdaptyRemoteConfig` girdisi taşır. Kullanıcının tercihine uyan dili seçin, ardından ihtiyaç duyduğunuz değerleri onun `data`'sından okuyun. ```typescript showLineNumbers try { const flow = await adapty.getFlow("YOUR_PLACEMENT_ID"); const config = flow.remoteConfigs?.find((c) => c.lang === "en") ?? flow.remoteConfigs?.[0]; const headerText = config?.data?.["header_text"]; } catch (error) { // handle the error } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra, onları görsel olarak çekici bir sayfaya render edip birleştirme zamanı gelir. Tasarımın çeşitli cep telefonu ekranlarına ve yönlendirmelerine uyum sağladığından emin olarak farklı cihazlarda kesintisiz ve kullanıcı dostu bir deneyim sunun. :::warning Adapty analizlerinin huniler ve A/B testleri için bilgi yakalayabilmesi adına, aşağıda açıklandığı gibi [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls-react-native#track-paywall-view-events) emin olun. ::: Flow'u görüntülemeyi tamamladıktan sonra, bir satın alma akışı kurmaya devam edin. Kullanıcı bir satın alma yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metoduyla ilgili ayrıntılar için [Satın alma işlemleri](react-native-making-purchases) bölümünü okuyun. [Yedek (fallback) paywall oluşturmanızı](react-native-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı veya kullanılabilir önbellek olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme olaylarını izleme \{#track-paywall-view-events\} Adapty, flow'larınızın performansını ölçmenize yardımcı olur. Satın almalarla ilgili verileri otomatik olarak toplarken, flow görüntülemelerini kaydetmek sizin girdinizi gerektirir; çünkü bir müşterinin bir flow'u ne zaman gördüğünü yalnızca siz bilirsiniz. Bir flow görüntüleme olayını kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterlidir; bu, huniler ve A/B testlerindeki paywall metriklerinize yansıtılır. :::important [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından render edilen flow'ları ya da paywall'ları görüntülüyorsanız `.logShowFlow(flow)` çağrısına gerek yoktur. Bu durumlarda Adapty görüntülemeleri otomatik olarak izler. ::: ```typescript showLineNumbers await adapty.logShowFlow(flow); ``` İstek parametreleri: | Parametre | Zorunlu | Açıklama | | :-------- | :------- |:-------------------------------------------------------------------------------------| | **flow** | gerekli | `adapty.getFlow(placementId)` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. | </SDKv4> <SDKv3> Bir paywall'ı remote config kullanarak özelleştirdiyseniz, onu kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini uygulamanız gerekir. Remote config, ihtiyaçlarınıza göre uyarlanmış esneklik sunduğundan, neyin dahil edileceği ve paywall view'inizin nasıl görüneceği sizin kontrolünüzdedir. Remote config'i getirmek için bir metot sağlıyoruz; böylece remote config ile yapılandırdığınız özel paywall'ınızı sergileme özerkliğine sahip olursunuz. ## Paywall remote config'ini alın ve gösterin \{#get-paywall-remote-config-and-present-it\} Bir paywall'un remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri çıkarın. ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: "YOUR_PLACEMENT_ID" }); const headerText = paywall.remoteConfig?.data?.["header_text"]; } catch (error) { // handle the error } ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfaya dönüştürme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olun; böylece farklı cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunulur. :::warning Adapty analitiğinin dönüşüm hunileri ve A/B testleri için bilgi toplayabilmesi amacıyla, aşağıda açıklandığı gibi [paywall görüntüleme etkinliğini kaydettiğinizden](present-remote-config-paywalls-react-native#track-paywall-view-events) emin olun. ::: Paywallı görüntüledikten sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma işlemi yaptığında, paywall'ınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](react-native-making-purchases) sayfasını okuyun. [Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](react-native-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilecek ve bu durumlarda bile sorunsuz bir deneyim sağlayacaktır. ## Paywall görüntüleme olaylarını izleme \{#track-paywall-view-events\} Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın almaları otomatik olarak takip ederken, paywall görüntüleme olaylarını kaydetmek için sizin müdahaleniz gerekir; çünkü bir kullanıcının paywall'ı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu, funnel ve A/B testlerindeki paywall metriklerinize yansıtılacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywall'ları gösteriyorsanız `.logShowPaywall(paywall)` metodunu çağırmanıza gerek yoktur. ::: ```typescript showLineNumbers await adapty.logShowPaywall(paywall); ``` İstek parametreleri: | Parametre | Zorunlu | Açıklama | | :---------- | :------- |:--------------------------------------------------------------------------------------------| | **paywall** | gerekli | Bir [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesi. | </SDKv3> --- # File: react-native-making-purchases --- --- title: "React Native SDK ile mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın almaları ve abonelikleri yönetme rehberi." --- Mobil uygulamanızda paywall göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, yalnızca bu paywall'ları göstermek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, satın almayı tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime geçmesini ve istedikleri işlemleri gerçekleştirmesini sağlayan kapıdır. Paywall'ınızda, kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa Adapty bunu satın alma sırasında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın. Aksi hâllerde [iOS'ta kullanıcının başlangıç teklifine uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlamak uygulamanızın yayın sürecinde reddedilmesine yol açabilir. Üstelik başlangıç teklifine hak kazanan kullanıcılardan tam ücret alınmasına neden olabilir. ::: Satın almaları doğrulayabilmemiz için [ilk yapılandırmayı](quickstart) hiçbir adımı atlamadan tamamladığınızdan emin olun. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir; bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](react-native-implement-paywalls-manually) göz atın. ::: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:-------------------------------------------------------------------------------------------------------------------------------| | **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>İstek başarılıysa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) nesnesi; kullanıcının uygulama içindeki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.</p><p>Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.</p> | :::warning **Not:** Apple'ın StoreKit sürümü 2.0'ın altında ve Adapty SDK sürümü 2.9.0'ın altındaysa, bunun yerine [Apple App Store paylaşılan gizli anahtarı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem Apple tarafından artık kullanımdan kaldırılmıştır. ::: ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu işlemin nasıl gerçekleşeceği uygulama mağazasına göre değişir: - App Store'da abonelik, abonelik grubu içinde otomatik olarak güncellenir. Kullanıcı bir gruptan abonelik satın alırken başka bir gruptan aktif aboneliği varsa, her iki abonelik de aynı anda aktif olur. - Google Play'de abonelik otomatik olarak güncellenemez. Geçişi, aşağıda açıklandığı şekilde mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka bir abonelikle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product, params); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Ücretli özelliklere erişim izni ver } break; case 'user_cancelled': // Kullanıcının satın almayı iptal ettiği durumu işle break; case 'pending': // Ertelenmiş satın almaları işle (örn. kullanıcı nakit ile offline ödeme yapacak) break; } } catch (error) { // Hatayı işle } ``` Ek istek parametresi: | Parametre | Zorunluluk | Açıklama | | :--------- | :------- | :----------------------------------------------------------- | | **params** | zorunlu | [`MakePurchaseParamsInput`](https://react-native.adapty.io/types/makepurchaseparamsinput) türünde bir nesne. | :::info **3.8.2+ sürümü**: `MakePurchaseParamsInput` yapısı güncellendi. `oldSubVendorProductId` ve `prorationMode` artık `subscriptionUpdateParams` altında iç içe yer alıyor; `isOfferPersonalized` ise üst seviyeye taşındı. ```javascript makePurchase(product, { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } }); ``` ::: Abonelikler ve değiştirme modları hakkında daha fazla bilgiyi Google Developer belgelerinde bulabilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değiştirme modları için önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değiştirme modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değiştirme modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik fatura dönemi sona erdiğinde gerçekleşir. ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanım sayfasını görüntülemek için: ```typescript showLineNumbers adapty.presentCodeRedemptionSheet(); ``` :::danger Gözlemlerimize göre bazı uygulamalarda Teklif Kodu Kullanım sayfası güvenilir çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunun için şu formattaki URL'yi açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin birkaç aylık yenilenmez abonelik), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { android: { pendingPrepaidPlansEnabled: true } }); ``` --- # File: react-native-restore-purchase --- --- title: "React Native SDK ile mobil uygulamada satın almaları geri yükleme" description: "Kesintisiz bir kullanıcı deneyimi sağlamak için Adapty'de satın almaların nasıl geri yükleneceğini öğrenin." --- Hem iOS hem de Android'de satın almaları geri yükleme özelliği, kullanıcıların abonelikler veya uygulama içi satın almalar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden erişmesini sağlar. Bu özellik, uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywallerde satın almalar, sizin tarafınızdan herhangi bir ek kod yazmaya gerek kalmadan otomatik olarak geri yüklenir. Bu durum sizin için geçerliyse bu adımı atlayabilirsiniz. ::: Paywalli özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın alımı geri yüklemek için `.restorePurchases()` metodunu çağırın: ```typescript showLineNumbers try { const profile = await adapty.restorePurchases(); const isSubscribed = profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // restore access } } catch (error) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|-----------| | **Profile** | <p>Bir [`AdaptyProfile`](https://react-native.adapty.io/interfaces/adaptyprofile) nesnesi. Bu model, access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir.</p><p>Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.</p> | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: implement-observer-mode-react-native --- --- title: "React Native SDK'da Observer modu uygulama" description: "React Native SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modu uygulayın." --- Kendi satın alma altyapınız varsa ve henüz tamamen Adapty'ye geçmeye hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer Modu, gelişmiş analitik ve attribution ile analitik sistemlerle sorunsuz entegrasyon sunar. Bu ihtiyaçlarınızı karşılıyorsa yalnızca şunları yapmanız gerekir: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak Observer modu'nu etkinleştirin. Kurulum talimatlarını [React Native](sdk-installation-reactnative) için takip edin. 2. Mevcut satın alma altyapınızdan [işlemleri Adapty'ye bildirin](report-transactions-observer-mode-react-native). ### Observer modu kurulumu \{#observer-mode-setup\} Satın alma ve abonelik durumunu kendiniz yönetiyorsanız ve Adapty'yi yalnızca abonelik olayları ile analitik göndermek için kullanıyorsanız Observer modu'nu etkinleştirin. :::important Observer modu çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle işlemleri kendiniz yönettiğinizden emin olun. ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { observerMode: true, // Enable observer mode }); ``` Parametreler: | Parametre | Açıklama | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observer modu](observer-vs-full-mode)'nu kontrol eden boolean değer. Varsayılan değer `false`'tur. | ## Observer Modunda Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer modunda biraz ek kurulum gereklidir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir: 1. [Remote config paywall'lar](present-remote-config-paywalls-react-native) için paywall'ları her zamanki gibi gösterin. 3. Satın alma işlemleriyle [paywall'ları ilişkilendirin](report-transactions-observer-mode-react-native). --- # File: report-transactions-observer-mode-react-native --- --- title: "React Native SDK'da Observer Mode'da işlemleri raporlama" description: "React Native SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini raporlayın." --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+ (current)" default> Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App Store'dan gelen işlemleri manuel olarak raporlamanız gerekir. Analitik hatalarından kaçınmak için bunu uygulamanızı yayınlamadan **önce** ayarlamanız çok önemlidir. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanarak açıkça bildirin. :::warning **İşlem raporlamayı atlayın!** `reportTransaction` çağrısı yapmazsanız Adapty işlemi tanımaz, işlem analitikte görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, işlemi raporlarken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve doğru paywall analitiği sağlar. ```typescript showLineNumbers const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | <ul><li> iOS için: İşlemin tanımlayıcısı.</li><li> Android için: Satın almanın string tanımlayıcısı (`purchase.getOrderId`); burada satın alma, billing kütüphanesi [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | variationId | isteğe bağlı | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x (legacy)" default> Observer mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen satın almaları kendi başına takip edemez. App Store'dan gelen işlemleri raporlamanız veya geri yüklemeniz gerekir. Analitik hatalarından kaçınmak için bunu uygulamanızı yayınlamadan **önce** ayarlamanız çok önemlidir. Her işlemi açıkça bildirmek için her iki platformda da `reportTransaction` kullanın; Adapty'nin işlemi tanıdığından emin olmak için Android'de ek bir adım olarak `restorePurchases` kullanın. :::warning **İşlem raporlamayı atlamayın!** Bu metotları çağırmazsanız Adapty işlemi tanımaz, işlem analitikte görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'larını kullanıyorsanız, işlemi raporlarken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve doğru paywall analitiği sağlar. ```typescript showLineNumbers if (Platform.OS === 'android') { try { await adapty.restorePurchases(); } catch (error) { // handle the error } } ... const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | <ul><li> iOS, StoreKit 1 için: bir [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</li><li> iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</li><li> Android için: Satın almanın string tanımlayıcısı (`purchase.getOrderId`); burada satın alma, billing kütüphanesi [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | variationId | isteğe bağlı | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> <TabItem value="old2" label="Adapty SDK up to 3.2.x (legacy)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **İşlemleri raporlama** - 3.1.x'e kadar olan sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel raporlama gerekmez. - 3.2 sürümü Observer Mode'u desteklememektedir. </TabItem> <TabItem value="kotlin" label="Android and Android-based cross-platforms" default> **İşlemleri raporlama** Observer Mode'da bir işlemi Adapty'ye raporlamak için `restorePurchases` kullanın; ayrıntılar [Mobil Kodda Satın Almaları Geri Yükleme](react-native-restore-purchase) sayfasında açıklanmaktadır. :::warning **İşlem raporlamayı atlamayın!** `restorePurchases` çağrısı yapmazsanız Adapty işlemi tanımaz, işlem analitikte görünmez ve entegrasyonlara gönderilmez. ::: </TabItem> </Tabs> **Paywall'ları işlemlerle ilişkilendirme** Adapty SDK, satın almaların kaynağını belirleyemez; çünkü bunları siz işliyorsunuzdur. Bu nedenle Observer mode'da paywall ve/veya A/B testi kullanmayı planlıyorsanız, app store'dan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Bunu uygulamanızı yayınlamadan önce doğru şekilde ayarlamak önemlidir; aksi takdirde analitikte hatalara yol açar. ```typescript const variationId = paywall.variationId; try { await adapty.setVariationId('transactionId', variationId); } catch (error) { // handle the `AdaptyError` } ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | ------------- | ---------- | ---------------------------------------------------------- | | transactionId | zorunlu | <p>iOS, StoreKit 1 için: bir [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</p><p>iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</p><p>Android için: Satın almanın string tanımlayıcısı (purchase.getOrderId); burada satın alma, billing kütüphanesi [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</p> | | variationId | zorunlu | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> </Tabs> --- # File: react-native-troubleshoot-purchases --- --- title: "React Native SDK'da satın alma sorunlarını giderme" description: "React Native SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, React Native SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrıldı, ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor, ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu genellikle Google Play Store kurulumunun eksik olduğuna ya da yapılandırma sorunlarına işaret eder. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## makePurchase iki kez çağrılıyor \{#makepurchase-is-invoked-twice\} **Sorun**: Aynı satın alma için `makePurchase` metodu birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya kullanıcının hızlı art arda işlem yapması nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: [Google Play kurulum adımlarını](initial-android) eksiksiz tamamladığınızdan emin olun. ## Observer modda AdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **Sorun**: Observer modda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmanız ya da observer modda satın almaları kendi tarafınızda yönetmeniz gerekir. Daha fazla bilgi için [Observer modunu uygulama](implement-observer-mode-react-native) bölümüne bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan fatura kullanılamaz hatası alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın kullanılamadığını belirten bir Google Play Billing Library hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Play Store belgelerinden daha fazla bilgi edinebilirsiniz: [BillingResult yanıt kodlarını yönetin](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamadı \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamıyor hatası alıyorsunuz. **Neden**: Bu genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu adım çoğunlukla sandbox ile ilgili satın alma tamamlama işleyicisi sorunlarını çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekirse SDK'yı [geçiş kılavuzlarını](react-native-sdk-migration-guides) kullanarak en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüştür. --- # File: react-native-identifying-users --- --- title: "React Native SDK'da kullanıcıları tanımlama" description: "Adapty SDK ile React Native uygulamanızda kullanıcıları nasıl tanımlayacağınızı öğrenin." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamalısınız. Kullanıcıları Customer User ID'leri ile [Profiller](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu tarafı API](getting-started-with-server-side-api)'sinde kullanabilirsiniz. ### Yapılandırma sırasında customer user ID ayarlama \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçirin: ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID" }); ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Yapılandırma sonrasında customer user ID ayarlama \{#setting-customer-user-id-after-configuration\} SDK yapılandırmasında kullanıcı ID'niz yoksa, bunu daha sonra istediğiniz zaman `.identify()` metoduyla ayarlayabilirsiniz. Bu metodun en yaygın kullanım durumları; kayıt veya yetkilendirme sonrasında, yani kullanıcı anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçtiğinde ortaya çıkar. ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // successfully identified } catch (error) { // handle the error } ``` İstek parametreleri: - **Customer User ID** (zorunlu): bir string kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda Adapty'nin sunucuları o kullanıcıya ait bilgilere zaten sahiptir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmaya otomatik olarak geçer. Anonim kullanıcıya özel nitelikler veya üçüncü taraf ağlardan attribution gibi veriler ilettiyseniz, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden istemeniz gerektiğini unutmayın. ::: ### Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak kullanıcının istediğiniz zaman çıkış yapmasını sağlayabilirsiniz: ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` Ardından `.identify()` metodunu kullanarak kullanıcıyı tekrar giriş yaptırabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle ilişkilendirir; böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir. Her kullanıcı için oluşturulan kararlı bir UUID kullanın ve aynı hesap için farklı cihazlarda da bu UUID'yi yeniden kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş kalır. Token'ı iki şekilde ayarlayabilirsiniz: SDK etkinleştirmesi sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmelisiniz. Yalnızca token'ı geçerseniz, işleme dahil edilmez. ::: ```typescript showLineNumbers // During configuration: adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID", ios: { appAccountToken: "YOUR_APP_ACCOUNT_TOKEN" }, }); // Or when identifying users try { await adapty.identify("YOUR_USER_ID", { ios: {appAccountToken: 'YOUR_APP_ACCOUNT_TOKEN'} }); // successfully identified } catch (error) { // handle the error } ``` ### Gizlenmiş hesap ID'leri ayarlama (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak için belirli kullanım durumlarında gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in kullanıcı bilgilerini anonim tutarken satın almaları tanımlamasına yardımcı olur; bu durum özellikle sahtecilik önleme ve analitik açısından önemlidir. Uygulamanız hassas kullanıcı verilerini işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri ayarlamanız gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını ifşa etmeden satın almaları takip etmesine olanak tanır. ```typescript showLineNumbers // During configuration: adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID", android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' } }); // Or when identifying users try { await adapty.identify("YOUR_USER_ID", { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' } }); // successfully identified } catch (error) { // handle the error } ``` ## Cihazlar arası kullanıcıları tespit etme \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: react-native-setting-user-attributes --- --- title: "React Native SDK'da kullanıcı nitelikleri ayarlama" description: "Adapty SDK ile React Native uygulamanızda kullanıcı niteliklerini ve profil verilerini nasıl güncelleyeceğinizi öğrenin." --- Uygulamanızın kullanıcılarına e-posta, telefon numarası gibi isteğe bağlı nitelikler ekleyebilirsiniz. Bu nitelikleri kullanarak kullanıcı [segmentleri](segments) oluşturabilir ya da bunları CRM'de görüntüleyebilirsiniz. ### Kullanıcı niteliklerini ayarlama \{#setting-user-attributes\} Kullanıcı niteliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```typescript showLineNumbers // Only for TypeScript validation const params: AdaptyProfileParameters = { email: 'email@email.com', phoneNumber: '+18888888888', firstName: 'John', lastName: 'Appleseed', gender: 'other', birthday: new Date().toISOString(), }; try { await adapty.updateProfile(params); } catch (error) { // handle `AdaptyError` } ``` Daha önce `updateProfile` metoduyla ayarladığınız niteliklerin sıfırlanmayacağını unutmayın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen `<Key>` anahtarları ve `<Value>` değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı nitelikleri \{#custom-user-attributes\} Kendi özel niteliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi düzeyi gibi değerler olabilir. Bu nitelikleri segmentlerde kullanarak hedefli paywall'lar ve teklifler oluşturabilir, ayrıca analitik amaçlarla hangi ürün metriklerinin geliri en çok etkilediğini anlamak için de kullanabilirsiniz. ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); } catch (error) { // handle `AdaptyError` } ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```typescript showLineNumbers try { // to remove a key, pass null as its value await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); } catch (error) { // handle `AdaptyError` } ``` Bazen daha önce hangi özel niteliklerin ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı nitelikleri farklı cihazlardan herhangi bir zamanda gönderilebilir, bu nedenle sunucudaki nitelikler son senkronizasyondan bu yana değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel nitelik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ve şunlardan herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakterlik bir string veya float olabilir. --- # File: react-native-listen-subscription-changes --- --- title: "React Native SDK'da abonelik durumunu kontrol etme" description: "React Native uygulamanızda müşteriyi elde tutmayı artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek son derece kolaydır. Ürün kimliklerini kodunuza manuel olarak eklemenize gerek yok. Bunun yerine, etkin bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. <details> <summary>Abonelik durumunu kontrol etmeye başlamadan önce (Genişletmek için tıklayın)</summary> - iOS için [App Store Server Notifications](enable-app-store-server-notifications) ayarlarını yapın - Android için [Real-time Developer Notifications (RTDN)](enable-real-time-developer-notifications-rtdn) ayarlarını yapın </details> ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) nesnesinin özellikleridir. Profili uygulamanız başladığında, örneğin [bir kullanıcıyı tanımladığınızda](react-native-identifying-users#setting-customer-user-id-on-configuration), almanızı ve ardından değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini defalarca istemek zorunda kalmadan kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için aşağıdaki [Abonelik durumu güncellemelerini dinleme](react-native-listen-subscription-changes) bölümünde açıklandığı şekilde profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Access level'ı sunucudan alma \{#retrieving-the-access-level-from-the-server\} Access level'ı sunucudan almak için `.getProfile()` metodunu kullanın: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- | ------------------------------------------------------------ | | Profile | <p>Bir [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) nesnesi. Genellikle, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.</p><p></p><p>`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (örneğin internet bağlantısı yoksa) Adapty SDK sunucudan bilgi alamazsa önbellekteki veriler döndürülür. Adapty SDK'nın `AdaptyProfile` önbelleğini düzenli aralıklarla güncelleyerek bilgileri mümkün olduğunca güncel tuttuğunu da belirtmek gerekir.</p> | `.getProfile()` metodu, access level durumunu alabileceğiniz kullanıcı profilini sağlar. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız "sports" ve "science" access level'ları oluşturabilirsiniz. Ancak çoğu durumda yalnızca bir access level'a ihtiyaç duyarsınız; bu durumda varsayılan "premium" access level'ını kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels?.["premium"]?.isActive; if (isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj almak için bazı ek yapılandırmalar yapmanız gerekir: ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addEventListener('onLatestProfileLoad', profile => { // handle any changes to subscription state }); ``` Adapty, uygulama başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'da uygulanan önbellek, profilin abonelik durumunu depolar. Bu sayede sunucu erişilemez olsa bile önbellekteki veriler kullanılarak profilin abonelik durumu hakkında bilgi edinilebilir. Ancak önbellekten doğrudan veri talep etmenin mümkün olmadığını belirtmek gerekir. SDK, profille ilgili güncelleme veya değişiklik olup olmadığını kontrol etmek için her dakika periyodik olarak sunucuyu sorgular. Yeni işlemler veya başka güncellemeler gibi herhangi bir değişiklik varsa, önbellekteki verilerle sunucu arasında senkronizasyon sağlamak amacıyla bu değişiklikler önbelleğe iletilir. --- # File: react-native-deal-with-att --- --- title: "React Native SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumu ve yönetimini kolaylaştırmak için React Native'de Adapty'ye başlayın." --- Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama takip yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. ```typescript showLineNumbers try { await adapty.updateProfile({ // you can also pass a string value (validated via tsc) if you prefer appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); } catch (error) { // handle `AdaptyError` } ``` :::warning Bu değeri, değiştiği anda mümkün olduğunca erken göndermenizi önemle tavsiye ederiz. Yalnızca bu durumda veriler, yapılandırdığınız entegrasyonlara zamanında iletilecektir. ::: --- # File: kids-mode-react-native --- --- title: "React Native SDK'da Kids Mode" description: "Apple ve Google politikalarına uymak için Kids Mode'u kolayca etkinleştirin. React Native SDK'da IDFA, GAID veya reklam verisi toplanmaz." --- React Native uygulamanız çocuklara yönelikse, [Apple](https://developer.apple.com/kids/) ve [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adım onu bu politikalara uyacak ve uygulama mağazası incelemelerini geçecek şekilde yapılandırmanıza yardımcı olur. :::important iOS'ta Kids Mode, tüm IDFA, AdSupport ve AppTrackingTransparency kodunu derleme dışında bırakan `KidsMode` Swift package trait'i aracılığıyla etkinleştirilir. v4 SDK'yı (yerel iOS SDK'yı Swift Package Manager aracılığıyla yükler) ve **Xcode 26** veya sonrasını gerektirir. Aşağıdaki [iOS Podfile'ınızdaki güncellemeler](#updates-in-your-ios-podfile) bölümüne bakın. ::: ## Ne gereklidir? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Reklam Kimliği (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunlara ek olarak, müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `<Ad.Soyad>` formatındaki kullanıcı kimliği, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilebilir. Çocuk Modu için en iyi uygulama, uyumu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (örneğin karma kimlikler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Çocuk Modunu Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamanı devre dışı bırakmanız gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzdaki güncellemeler \{#updates-in-your-mobile-app-code\} Politikalara uymak için Adapty SDK'sını etkinleştirirken kullanıcının IDFA (iOS), GAID/AAID (Android) ve IP adresi toplanmasını devre dışı bırakın: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { // Disable IP address collection ipAddressCollectionDisabled: true, // Disable IDFA collection on iOS ios: { idfaCollectionDisabled: true, }, // Disable Google Advertising ID collection on Android android: { adIdCollectionDisabled: true, }, }); ``` ### iOS Podfile'ınızdaki güncellemeler \{#updates-in-your-ios-podfile\} App Store Kids Category (veya COPPA uyumluluğu) için, yerel iOS SDK'sı tüm IDFA, AdSupport ve AppTrackingTransparency kodunu derleme dışında bırakan `KidsMode` Swift package trait'i ile derlenmelidir. React Native, yerel SDK'yı package trait'lerini iletemeyen Swift Package Manager aracılığıyla yükler, bu yüzden SDK, trait'i sizin için uygulayan bir Podfile yardımcısı sağlar. Bu adım **Xcode 26** veya sonrasını gerektirir. `ios/Podfile` içinde, yardımcıyı require edin ve onu `react_native_post_install`'dan **sonra** çağırın: ```ruby showLineNumbers title="ios/Podfile" require Pod::Executable.execute_command('node', ['-p', 'require.resolve( "react-native-adapty/ios/adapty_kids_mode.rb", {paths: [process.argv[1]]}, )', __dir__]).strip # ... post_install do |installer| react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false ) adapty_enable_kids_mode(installer) end ``` Ardından `pod install` komutunu çalıştırın: ```sh showLineNumbers title="Shell" cd ios && pod install ``` Kids Mode'un etkin olduğunu doğrulamak için `adapty.activate(...)` log satırının `kids_mode_enabled: true` bildirdiğini kontrol edin. Yardımcı çağrısını `post_install` içinde kalıcı olarak tutun — React Native, her `pod install`'da Swift package referanslarını yeniden oluşturur ve yardımcı, trait'i her seferinde yeniden uygular. ### Android manifest'inizdeki güncellemeler \{#updates-in-your-android-manifest\} :::note Uygulamanız **yalnızca** çocuklara yönelikse ve Android 13 (API 33) veya üzeri sürümleri hedefliyorsa, Google Play `AD_ID` iznini talep etmemenizi gerektirir. Uygulamanızdaki başka bir SDK (analitik, attribution veya reklam), manifest birleştirme yoluyla bu izni ekleyebilir. `adIdCollectionDisabled` ayarı, Adapty'nin kimliği toplamasını durdurur; ancak başka bir SDK'nın tanımladığı bir izni kaldırmaz. ::: İzni kaldırmak için `android/app/src/main/AndroidManifest.xml` dosyasındaki `<manifest>` öğesinin içine aşağıdakini ekleyin. `<manifest>` öğesi `xmlns:tools="http://schemas.android.com/tools"` bildirimini içermelidir. ```xml showLineNumbers title="AndroidManifest.xml" <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" /> ``` --- # File: react-native-get-onboardings --- --- title: "React Native SDK'da onboarding'leri getirme" description: "React Native için Adapty'de onboarding'leri nasıl getireceğinizi öğrenin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırıldı ve gelecekteki bir sürümde kaldırılacak.** Artık düzeltme veya iyileştirme almıyorlar. Bunun yerine [flow'ları](react-native-get-pb-paywalls) kullanın: bir WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu da size daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığının olmaması avantajını sağlar. Başlamak için bkz. [Flow'ları ve paywall'ları getirme](react-native-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleme](react-native-present-paywalls). ::: Adapty Kontrol Paneli'ndeki builder ile [onboarding'inizin görsel kısmını tasarladıktan](design-onboarding) sonra, onu React Native uygulamanızda görüntüleyebilirsiniz. Bu süreçteki ilk adım, placement ile ilişkili onboarding'i ve view yapılandırmasını aşağıda açıklandığı gibi getirmektir. Başlamadan önce şunlardan emin olun: 1. [Adapty React Native SDK](sdk-installation-reactnative) sürüm 3.8.0 veya üzerini yüklediniz. 2. Bir [onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. ## Onboarding'i Getir \{#fetch-onboarding\} No-code builder'ımızla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirmesi ve göstermesi gereken bir yapılandırma içeren konteyner olarak saklanır. Bu konteyner tüm deneyimi yönetir: hangi içeriğin görüneceği, nasıl sunulacağı ve kullanıcı etkileşimlerinin (sınav yanıtları veya form girişleri gibi) nasıl işleneceği. Konteyner aynı zamanda analitik olaylarını otomatik olarak takip ettiğinden ayrıca görünüm takibi uygulamanıza gerek yoktur. En iyi performans için, kullanıcılara göstermeden önce görsellerin indirilmesine yeterli zaman tanımak amacıyla onboarding yapılandırmasını erken getirin. Bir onboarding almak için `getOnboarding` metodunu kullanın: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboarding(placementId, locale); // the requested onboarding } catch (error) { // handle the error } ``` Ardından bir görünüm örneği oluşturmak için `createOnboardingView` metodunu çağırın. :::warning `createOnboardingView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `createOnboardingView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createOnboardingView} from 'react-native-adapty/dist/ui'; if (onboarding.hasViewConfiguration) { try { const view = await createOnboardingView(onboarding); } catch (error) { // handle the error } } else { //use your custom logic } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |-------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil içindir, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum süresince güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en son sürümünü almanızı garanti eder.</p> | | **loadTimeoutMs** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenin biraz daha gerisinde zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşuyor olabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikleri içeren bir [`AdaptyOnboarding`](https://react-native.adapty.io/interfaces/adaptyonboarding) nesnesi. | ## Varsayılan kitle onboarding'i ile onboarding getirmeyi hızlandırın \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, onboarding getirme istediğinizden daha uzun sürebilir. Bu durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir onboarding göstermek isteyebilirsiniz. Bunu ele almak için, belirtilen placement'ın **All Users** kitlesi için onboarding'i getiren `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding'i Getir](#fetch-onboarding) bölümünde ayrıntılı olarak açıklandığı gibi `getOnboarding` metoduyla onboarding getirmek olduğunu anlamak önemlidir. :::warning `getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı tercih edin; çünkü ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlara yol açabilir; ya geriye dönük uyumlu tasarımlar gerektirirsiniz ya da eski sürümlerin yanlış görüntülenebileceğini kabul etmek durumunda kalırsınız. - **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülkeye, attribution'a veya özel niteliklere göre hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı getirme bu dezavantajlardan daha önemliyse `getOnboardingForDefaultAudience` kullanın (aşağıda gösterildiği gibi). Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı şekilde `getOnboarding` kullanın. ::: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboardingForDefaultAudience(placementId, locale); // the requested onboarding } catch (error) { // handle the error } ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil içindir, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>Varsayılan olarak SDK, sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız internet bağlantısıyla karşılaştığını düşünüyorsanız, varsa önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum süresince güvenle kullanılabilir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken onboarding'lerinizin her zaman en son sürümünü almanızı garanti eder.</p> | --- # File: react-native-present-onboardings --- --- title: "React Native SDK'da onboarding sunma" description: "Dönüşümleri ve geliri artırmak için React Native'de onboarding'lerin nasıl sunulacağını keşfedin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırıldı ve gelecekteki bir sürümde kaldırılacak.** Artık düzeltme veya iyileştirme almıyorlar. Bunun yerine [flow'ları](react-native-get-pb-paywalls) kullanın: bir WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu da size daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığının olmaması avantajını sağlar. Başlamak için bkz. [Flow'ları ve paywall'ları getirme](react-native-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleme](react-native-present-paywalls). ::: Onboarding'i builder ile özelleştirdiyseniz, kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yok. Böyle bir onboarding; hem ne gösterileceğini hem de nasıl gösterileceğini kendi içinde barındırır. Başlamadan önce şunları sağlayın: 1. [Adapty React Native SDK](sdk-installation-reactnative) 3.8.0 veya daha yeni bir sürümünü yüklemiş olun. 2. Bir [onboarding oluşturmuş](create-onboarding) olun. 3. Onboarding'i bir [placement](placements)'a eklemiş olun. Adapty React Native SDK, onboarding'leri sunmak için iki yöntem sunar: - **React bileşeni**: Yerleşik bileşen, uygulamanızın mimarisine ve navigasyon sistemine entegre etmenizi sağlar. - **Modal sunum** ## React bileşeni \{#react-component\} Onboarding'i mevcut bileşen ağacınıza gömmek için `AdaptyOnboardingView` bileşenini doğrudan React Native bileşen hiyerarşinizde kullanın. Yerleşik bileşen, uygulamanızın mimarisine ve navigasyon sistemine entegre etmenizi sağlar. :::note Android'de `AdaptyOnboardingView` için görsel bir render sorununun önüne geçmek amacıyla ek yapılandırma yapmanızı öneririz. Bkz. [Android'de sistem arayüzü onboarding içeriğiyle çakışıyor](#system-ui-overlaps-onboarding-content-on-android). ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="old" label="SDK version < 3.14" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { return ( <AdaptyOnboardingView onboarding={onboarding} style={{ flex: 1 }} eventHandlers={{ onAnalytics(event, meta) { // Handle analytics events }, onClose(actionId, meta) { // Handle close actions }, onCustom(actionId, meta) { // Handle custom actions }, onPaywall(actionId, meta) { // Handle paywall actions }, onStateUpdated(action, meta) { // Handle state updates }, onFinishedLoading(meta) { // Handle when onboarding finishes loading }, onError(error) { // Handle errors }, }} /> ); } ``` </TabItem> </Tabs> ## Modal sunum \{#modal-presentation\} Onboarding'i kullanıcının kapatabileceği bağımsız bir ekran olarak göstermek için `createOnboardingView` metoduyla oluşturulan `view` üzerinde `view.present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Onboarding'i tekrar göstermeniz gerekirse `createOnboardingView`'ı bir kez daha çağırarak yeni bir `view` örneği oluşturun. :::warning Aynı `view`'ı yeniden oluşturmadan kullanmak yasaktır. Bu, `AdaptyUIError.viewAlreadyPresented` hatasına neden olur. ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView(onboarding); // Optional: handle onboarding events (close, custom actions, etc) // view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> <TabItem value="old" label="SDK version < 3.14" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView(onboarding); view.setEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ### iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `present()` metoduna `iosPresentationStyle` parametresini geçirerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `'full_screen'` (varsayılan) veya `'page_sheet'` değerlerini kabul eder. ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## Onboarding sırasında yükleyici \{#loader-during-onboarding\} React Native'de onboarding sunarken, onboarding görünmeden önce kısa bir beyaz yanıp sönme veya yükleme ekranı fark edebilirsiniz. Bu, altta yatan native view başlatılırken gerçekleşir. İhtiyacınıza ve iş akışınıza bağlı olarak bunu farklı şekillerde ele alabilirsiniz. #### onFinishedLoading ile açılış ekranını kontrol etme \{#control-splash-screen-using-onfinishedloading\} :::note Bu yaklaşım yalnızca React bileşeni kullanılırken geçerlidir. Modal sunum için mevcut değildir. ::: React Native için önerilen yaklaşım, onboarding tamamen yüklenene kadar açılış ekranınızı veya özel bir katmanı görünür tutmak, ardından manuel olarak gizlemektir. React bileşenini (`AdaptyOnboardingView`) kullanırken, açılış ekranınızı veya katmanınızı gizlemeden önce `onFinishedLoading` olayını bekleyin: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const [isLoading, setIsLoading] = useState(true); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => { // Hide your splash screen or custom overlay here setIsLoading(false); }, []); return ( <> <AdaptyOnboardingView onboarding={onboarding} onFinishedLoading={onFinishedLoading} // ... other callbacks /> {isLoading && <YourCustomLoadingOverlay />} </> ); } ``` </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const [isLoading, setIsLoading] = useState(true); return ( <> <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onFinishedLoading(meta) { // Hide your splash screen or custom overlay here setIsLoading(false); }, // ... other handlers }} /> {isLoading && <YourCustomLoadingOverlay />} </> ); } ``` </TabItem> </Tabs> #### Native yükleyiciyi özelleştirme \{#customize-native-loader\} :::important Expo yönetilen iş akışı, özel native layout'lar yerleştirmeyi desteklemez (ör. Android'de `res/layout`). Expo uygulamalarında açılış ekranını kontrol etmek veya React Native katmanı kullanmak tek geçerli çözümdür. ::: Native yükleyiciyi Android ve iOS'ta platforma özgü layout'larla değiştirebilirsiniz. Modal sunum kullanıyorsanız bu tek seçeneğinizdir. Ancak bu yaklaşım genellikle React Native uygulamaları için daha az pratiktir: - Ayrı Android ve iOS uygulamaları gerektirir - Expo yönetilen iş akışıyla uyumlu değildir Her platform için bir yer tutucu tanımlayın: - **iOS**: Xcode projenize `AdaptyOnboardingPlaceholderView.xib` ekleyin. [Daha fazla bilgi](ios-present-onboardings#add-smooth-transitions-between-the-splash-screen-and-onboarding). - **Android**: `res/layout` dizininde `adapty_onboarding_placeholder_view.xml` oluşturun ve bir yer tutucu tanımlayın. [Daha fazla bilgi](android-present-onboardings#add-smooth-transitions-between-the-splash-screen-and-onboarding). ## Onboardinglerde linklerin nasıl açıldığını özelleştirme \{#customize-how-links-open-in-onboardings\} :::important Onboardinglerde linklerin nasıl açıldığını özelleştirme, Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboardinglerdeki linkler uygulama içi tarayıcıda açılır. Bu, web sayfalarını uygulamanız içinde göstererek kullanıcıların uygulama değiştirmeden görüntülemesine olanak tanır ve kesintisiz bir kullanıcı deneyimi sunar. Linkleri bunun yerine harici tarayıcıda açmayı tercih ediyorsanız, `externalUrlsPresentation` parametresini `WebPresentation.BrowserOutApp` olarak ayarlayarak bu davranışı özelleştirebilirsiniz: <Tabs groupId="rn-onboarding-views" queryString> <TabItem value="component" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} externalUrlsPresentation={WebPresentation.BrowserOutApp} // default – BrowserInApp onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="modal" label="Modal presentation"> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView( onboarding, { externalUrlsPresentation: WebPresentation.BrowserOutApp } // default – BrowserInApp ); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## Sorun giderme \{#troubleshooting\} ### Android'de sistem arayüzü onboarding içeriğiyle çakışıyor \{#system-ui-overlaps-onboarding-content-on-android\} :::note Bu ayar yalnızca bare React Native projelerinde desteklenmektedir. Expo yönetilen iş akışı kullanıyorsanız bu Android kaynağını doğrudan ekleyemezsiniz. Bu ayarı uygulamak için ilgili Android kaynağını ekleyen özel bir Expo config plugin oluşturmanız ve bunu app.config.js'e kaydetmeniz gerekir. Bu zorunludur çünkü Expo, native Android projesini sizin adınıza yönetir. ::: Android'de `AdaptyOnboardingView` kullanırken durum çubuğu ve gezinme çubuğu gibi sistem arayüzü öğeleri paywall içeriğinin üzerinde görünebilir. Bunu önlemek için uygulamanıza aşağıdaki boolean kaynağını ekleyin: 1. `android/app/src/main/res/values` dizinine gidin. `bools.xml` dosyası yoksa oluşturun. 2. Aşağıdaki kaynağı ekleyin: ```xml <resources> <bool name="adapty_onboarding_enable_safe_area_paddings">false</bool> </resources> ``` Bu değişikliklerin uygulamanızdaki tüm onboarding'ler için genel olarak uygulandığını unutmayın. ## Sonraki adımlar \{#next-steps\} Onboarding'inizi sunduktan sonra [kullanıcı etkileşimlerini ve olayları ele almak](react-native-handling-onboarding-events) isteyeceksiniz. Kullanıcı eylemlerine yanıt vermek ve analizleri takip etmek için onboarding olaylarını nasıl ele alacağınızı öğrenin. --- # File: react-native-handling-onboarding-events --- --- title: "React Native SDK'da onboarding olaylarını yönetin" description: "React Native'de Adapty kullanarak onboarding ile ilgili olayları yönetin." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırıldı ve gelecekteki bir sürümde kaldırılacak.** Artık düzeltme veya iyileştirme almıyorlar. Bunun yerine [flow'ları](react-native-get-pb-paywalls) kullanın: bir WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu da size daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığının olmaması avantajını sağlar. Başlamak için bkz. [Flow'ları ve paywall'ları getirme](react-native-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleme](react-native-present-paywalls). ::: Başlamadan önce şunları kontrol edin: Onboarding builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olayları nasıl ele alacağınız, hangi sunum yaklaşımını kullandığınıza bağlıdır: - **Modal sunum**: Tüm onboarding görünümleri için olayları işleyen olay işleyicilerinin kurulmasını gerektirir - **React bileşeni**: Olayları doğrudan widget içindeki satır içi callback parametreleri aracılığıyla işler 1. [Adapty React Native SDK](sdk-installation-reactnative) 3.8.0 veya daha yeni bir sürümünü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Mobil uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için olay işleyicilerini uygulayın: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> React bileşeninde, olayları `AdaptyOnboardingView` bileşenindeki tekil olay işleyici prop'ları aracılığıyla yönetirsiniz: ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> Modal sunum için event handler metodunu uygulayın. :::important `setEventHandlers` metodunu birden fazla kez çağırmak, sağladığınız handler'ları geçersiz kılar ve ilgili olaylar için hem varsayılan hem de daha önce ayarlanan handler'ların yerini alır. ::: ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onAnalytics(event, meta) { // Analitik olaylarını takip et }, onClose(actionId, meta) { // Kapatma eylemini işle view.dismiss(); return true; }, onCustom(actionId, meta) { // Özel eylemleri işle }, onPaywall(actionId, meta) { // Paywall eylemlerini işle }, onStateUpdated(action, meta) { // Kullanıcı girişi güncellemelerini işle }, onFinishedLoading(meta) { // Onboarding yüklemesi tamamlandı }, onError(error) { // Yükleme hatalarını işle }, }); try { await view.present(); } catch (error) { // hatayı işle } ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> SDK version < 3.14 için yalnızca modal sunum desteklenmektedir: ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onAnalytics(event, meta) { // Analitik olaylarını takip et }, onClose(actionId, meta) { // Kapatma eylemini işle view.dismiss(); return true; }, onCustom(actionId, meta) { // Özel eylemleri işle }, onPaywall(actionId, meta) { // Paywall eylemlerini işle }, onStateUpdated(action, meta) { // Kullanıcı girişi güncellemelerini işle }, onFinishedLoading(meta) { // Onboarding yüklemesi tamamlandı }, onError(error) { // Yükleme hatalarını işle }, }); try { await view.present(); } catch (error) { // hatayı işle } ``` </TabItem> </Tabs> ## Etkinlik türleri \{#event-types\} Aşağıdaki bölümler, hangi sunum yaklaşımını kullandığınızdan bağımsız olarak işleyebileceğiniz farklı etkinlik türlerini açıklamaktadır. ### Özel eylemleri yönetme \{#handle-custom-actions\} Builder'da bir butona **özel** eylem ekleyebilir ve ona bir ID atayabilirsiniz. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ardından bu ID'yi kodunuzda kullanabilir ve özel bir eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir butona dokunduğunda, olay işleyicisi **Action ID** parametresiyle tetiklenir ve bu parametre builder'daki **Action ID** ile eşleşir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onCustom={onCustom} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK sürümü < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, }); ``` </TabItem> </Tabs> <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allow_notifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### Onboarding yüklemesi tamamlandığında \{#finishing-loading-onboarding\} Bir onboarding yüklemesi tamamlandığında şu olay tetiklenir: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK sürüm 3.14 veya sonrası" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => { console.log('Onboarding loaded:', meta.onboardingId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onFinishedLoading={onFinishedLoading} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` </TabItem> </Tabs> <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### Onboarding'i kapatma \{#closing-onboarding\} Kullanıcı **Close** eylemine atanmış bir butona dokunduğunda onboarding kapatılmış sayılır. <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Kullanıcı onboarding'i kapattığında ne olacağını yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini göstermeyi durdurmanız gerekir. ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK sürüm 3.14 veya üzeri" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding, navigation }) { const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => { navigation.goBack(); }, [navigation]); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onClose={onClose} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onClose(actionId, meta) { await view.dismiss(); return true; }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK sürümü < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onClose(actionId, meta) { await view.dismiss(); return true; }, }); ``` </TabItem> </Tabs> <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### Paywall Açma \{#opening-a-paywall\} :::tip Onboarding içinde bir paywall açmak istiyorsanız bu olayı işleyin. Paywall kapatıldıktan sonra açmak istiyorsanız daha kolay bir yol var: kapat aksiyonunu işleyip olay verisine gerek kalmadan paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en kolay yolu, aksiyon ID'sini paywall placement ID'sine eşit yapmaktır. <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React bileşeni" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => { openPaywall(actionId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onPaywall={onPaywall} /> ); } const openPaywall = async (placementId) => { // Implement your paywall opening logic here }; ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> iOS'ta aynı anda yalnızca bir görünüm (paywall veya onboarding) ekranda gösterilebilir. Bir onboarding'in üzerine paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışırsanız bunun yerine paywall kapanır ve onboarding görünür kalır. Bunu önlemek için paywall'ı sunmadan önce her zaman onboarding görünümünü kapatın. ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onPaywall(actionId, meta) { view.dismiss().then(() => { openPaywall(actionId); }); }, }); const openPaywall = async (placementId) => { // Paywall açma mantığınızı buraya ekleyin }; ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK sürümü < 3.14"> :::note iOS'ta aynı anda yalnızca bir görünüm (paywall veya onboarding) ekranda gösterilebilir. Bir onboarding'in üzerine paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışırsanız bunun yerine paywall kapanır ve onboarding görünür kalır. Bunu önlemek için paywall'ı sunmadan önce her zaman onboarding görünümünü kapatın. ::: ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onPaywall(actionId, meta) { view.dismiss().then(() => { openPaywall(actionId); }); }, }); const openPaywall = async (placementId) => { // Paywall açma mantığınızı buraya uygulayın }; ``` </TabItem> </Tabs> <Details> <summary>Etkinlik örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### Navigasyonu İzleme \{#tracking-navigation\} Onboarding akışı sırasında çeşitli navigasyonla ilgili olaylar gerçekleştiğinde bir analitik etkinliği alırsınız: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK sürüm 3.14 veya üzeri" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => { trackEvent(event.name, meta.onboardingId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onAnalytics(event, meta) { trackEvent(event.name, meta.onboardingId); }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onAnalytics(event, meta) { trackEvent(event.name, meta.onboardingId); }, }); ``` </TabItem> </Tabs> `event` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `onboardingStarted` | Onboarding yüklendiğinde | | `screenPresented` | Herhangi bir ekran gösterildiğinde | | `screenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcının yanıtı) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir işlem yaptığında tetiklenir. | | `secondScreenPresented` | İkinci ekran gösterildiğinde | | `userEmailCollected` | Kullanıcının e-postası giriş alanı aracılığıyla toplandığında tetiklenir | | `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyaç duyuyorsanız [son ekrana `final` ID'sini atayın](design-onboarding). | | `unknown` | Tanınmayan olay türleri için. `name` (bilinmeyen olayın adı) ve `meta` (ek meta veriler) içerir | Her etkinlik, aşağıdakileri içeren `meta` bilgilerini barındırır: | Alan | Açıklama | |------------|-------------| | `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `screenClientId` | Mevcut ekranın tanımlayıcısı | | `screenIndex` | Mevcut ekranın akıştaki konumu | | `screensTotal` | Akıştaki toplam ekran sayısı | <Details> <summary>Etkinlik örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: react-native-onboarding-input --- --- title: "React Native SDK'da onboarding'lerden gelen verileri işleme" description: "Adapty SDK ile React Native uygulamanızda onboarding'lerden gelen verileri kaydedin ve kullanın." --- :::warning **Onboarding'ler SDK v4'te kullanımdan kaldırıldı ve gelecekteki bir sürümde kaldırılacak.** Artık düzeltme veya iyileştirme almıyorlar. Bunun yerine [flow'ları](react-native-get-pb-paywalls) kullanın: bir WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu da size daha akıcı animasyonlar, tutarlı bir yerel görünüm ve his, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığının olmaması avantajını sağlar. Başlamak için bkz. [Flow'ları ve paywall'ları getirme](react-native-get-pb-paywalls) ve [Flow'ları ve paywall'ları görüntüleme](react-native-present-paywalls). ::: Kullanıcılarınız bir sınav sorusunu yanıtladığında veya verilerini bir giriş alanına girdiğinde, `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Örneğin: ```javascript // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Process data }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Process data }, }} /> ``` Eylem formatını [buradan](https://react-native.adapty.io/types/onboardingstateupdatedaction) görebilirsiniz. <Details> <summary>Kaydedilen veri örnekleri (format sizin uygulamanızda farklı olabilir)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "elementType": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" }, "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "totalScreens": 3 } } // Example of a saved multi-select action { "elementId": "interests_selector", "elementType": "multi_select", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ], "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "totalScreens": 3 } } // Example of a saved input action { "elementId": "name_input", "elementType": "input", "value": { "type": "text", "value": "John Doe" }, "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "totalScreens": 3 } } // Example of a saved date picker action { "elementId": "birthday_picker", "elementType": "date_picker", "value": { "day": 15, "month": 6, "year": 1990 }, "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "totalScreens": 3 } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Girilen verileri kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi tekrar sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](react-native-setting-user-attributes) girilen verilerle güncellemeniz gerekir. Örneğin, kullanıcılardan `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmeleri için de bir alan ekliyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```javascript showLineNumbers // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }} /> ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboardinglardaki quizleri kullanarak, onboarding tamamlandıktan sonra gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara sporla ilgili deneyimlerini sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding oluşturucuda bir [quiz ekleyin](onboarding-quizzes) ve seçeneklerine anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel özellikler ayarlayın](react-native-setting-user-attributes). ```javascript showLineNumbers // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }} /> ``` 3. Her özel özellik değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda placement için bir [paywall gösterin](react-native-paywalls). Onboardinginizde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna yanıt olarak](react-native-handling-onboarding-events#opening-a-paywall) uygulayın. --- # File: react-native-sdk-call-order --- --- title: "React Native SDK'da çağrı sırası" description: "Premium erişim kayıplarını, eksik attribution verilerini ve aralıklı #2002 hatalarını önlemek için Adapty SDK metodlarını doğru sırayla çağırın." --- `adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağıramazsınız. Bu metod çözüme kavuşana kadar SDK'nın herhangi bir durumu yoktur. `activate()` tamamlanmadan veya bununla paralel olarak yapılan her çağrı [`#2002 notActivated`](react-native-handle-errors#custom-network-codes) hatasıyla başarısız olur. Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, o noktada `adapty.identify()` çağrısı yapın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metodları çağırmayın. Bu çağrıyla yarışan işlemler ya [`#3006 profileWasChanged`](react-native-handle-errors#custom-network-codes) hatasıyla başarısız olur ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP ID'leri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `adapty.activate` çağrısından önce bunları başlatın ve UID geri çağrımlarını bekleyin. Aksi takdirde MMP kimliği kısa ömürlü anonim bir profile bağlanır ve tanımlanmış profile her zaman aktarılamaz. AppsFlyer'a özgü ayrıntılar için bkz. [AppsFlyer](appsflyer). ## Doğru sıra \{#the-correct-order\} Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK metodlarını çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK entegre ediyorsanız gereklidir (AppsFlyer, Adjust, Branch, PostHog). - **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatmadan sonra topluyorsa gereklidir. Uygulama başlangıcında müşteri kullanıcı kimliğine sahipseniz, onu doğrudan `activate()` içine aktarın (adım 2a). Bu yol hiçbir zaman anonim profil oluşturmaz; dolayısıyla adım 4'e gerek yoktur. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analytics SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama açılışı, ilk adım | MMP'nin UID callback'ini bekleyin, örneğin `getAppsFlyerUID`. | | 2a | `adapty.activate('YOUR_PUBLIC_SDK_KEY', { customerUserId: 'YOUR_USER_ID' })` | Uygulama açılışı, adım 1'den sonra, müşteri kullanıcı kimliğiniz varsa | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `adapty.activate('YOUR_PUBLIC_SDK_KEY')` ile `customerUserId` olmadan | Uygulama açılışı, adım 1'den sonra, müşteri kullanıcı kimliğiniz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `adapty.updateAttribution(data, source, networkUserId)` | Adım 2'den sonra, herhangi bir kullanıcı işlemi çağrısından önce | MMP kimliklerinin doğru profile düşmesi için gereklidir. | | 4 | `await adapty.identify('YOUR_USER_ID')` | Adım 3'ten sonra (veya MMP yoksa adım 2'den sonra), adım 5'ten önce — yalnızca kimlik doğrulamayla 2b yolunda | Her zaman `await` kullanın. `identify` sırasındaki eşzamanlı çağrılar `#3006 profileWasChanged` hatasını üretir. | | 5 | `getPaywall`, `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız adım 4'ten sonra; aksi takdirde adım 3'ten sonra (veya MMP yoksa adım 2'den sonra) | Bu çağrılar kararlı bir profil gerektirir. | :::important Bu adımları atlamak, geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitle için döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar bir web checkout (Stripe, Paddle) üzerinden satın alım yapıp daha sonra uygulamayı yüklerse, cihazda ilk `activate()` çağrısı yeni ve anonim bir profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Auth akışından veya install referrer'dan müşteri kullanıcı kimliğini uygulama açılmadan önce çözebiliyorsanız, doğrudan `activate()` içine aktarın. Aksi takdirde web satın alımı, `identify('YOUR_USER_ID')` ve ardından `restorePurchases` çağırana kadar cihazda görünmez kalır. Her web checkout ile birlikte gönderilecek metadata için şuraya bakın: - [Stripe](stripe) - [Paddle](paddle) --- # File: react-native-optimize-paywall-fetching --- --- title: "React Native SDK'da paywall getirmeyi optimize etme" description: "Adapty paywall'larını güvenilir şekilde getirin: React Native için zamanlama, önbellek ve yedek paywall desenleri." --- React Native'de güvenilir bir paywall getirme işlemi üç şeyi başarır: hızlı render eder, kitleye yönelik paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz yedek paywall'a geçer. Aşağıdaki kurallar, bunu sağlamak için zamanlama, önbellek ve yedek paywall desenlerini kapsamaktadır. :::tip Bu kurallar, `adapty.activate()` ve `adapty.identify()` işlemlerinin zaten tamamlandığını varsayar. Daha fazla bilgi için bkz. [React Native SDK'da çağrı sırası](react-native-sdk-call-order). ::: ## Kurallar ve yaygın hatalar \{#rules-and-pitfalls\} | Bunu yap | Bunu yapma | Neden | |---|---|---| | Göstermek üzere olduğun placement'ı getir. | Uygulama açılışında tüm placement'ları eş zamanlı olarak önceden getir. | Toplu önceden getirme JS thread'ini bloklar ve bu süre zarfında siyah ekran görünür. | | Attribution'ın çözülmesine fırsat tanındıktan sonra — örneğin `activate`'ten 1–2 saniye sonra ya da `onProfileUpdate` tetiklendikten sonra — `getPaywall`'ı çağır. | `getPaywall`'ı kök bileşen mount'lanırken çağır. | Attribution henüz gelmemiştir. Paywall, varsayılan kitleye göre çözümlenir ve segmentler ile ASA kişiselleştirmesi sessizce atlanır. | | Her placement için bir `loadTimeoutMs` belirle ve bir [yedek paywall](fallback-paywalls) yapılandır. | `getPaywall`'ın sonuçlanmasını süresiz bekle. | Timeout olmazsa, bağlantısı zayıf olan kullanıcılar ağ çözümlenene kadar boş ekran görür — ya da uygulamayı kapatır. | Bkz. `fetchPolicy` ve `loadTimeoutMs` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products-react-native), doğru placement'ı seçmek için ise [Placement'lar](placements). ## Zayıf bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantının yaşandığı pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunları olan bölgeler): - İlk istek dışındaki her fetch işleminde `fetchPolicy: .returnCacheDataElseLoad` kullanın. - Adapty kontrol panelindeki her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeoutMs` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin. - Paywall görüntülemeyi `getProfile()` işlemine bağlamayın. `getPaywall` çağrısını bağımsız yapın; böylece yavaş bir profil yanıtı arayüzü bloke etmez. --- # File: react-native-show-aa-targeted-paywall --- --- title: "React Native SDK'da ilk başlatmada AA hedefli paywall gösterme" description: "React Native'de attribution uygulandığında Apple Ads kullanıcıları için bir paywall'ı hemen gösterin ve yükseltin; AdaptyProfile.appliedAttributionSources kullanılarak." --- Apple Ads (AA) attribution, `adapty.activate()` çağrısından sonra eşzamansız olarak gelir. İlk açılışta henüz gelmemiş olacağından `getPaywall`, varsayılan kitleye göre çözümlenir ve Apple Ads kullanıcıları AA segmentli paywallı göremez. Paywall'ı attribution gelene kadar bekletmek yerine, hemen bir tane gösterin ve AA attribution uygulandıktan sonra yenileyin — böylece Apple Ads kullanıcıları hedeflenmiş varyantı görürken diğer kullanıcılar hiç beklemeden paywalllarına erişir. `AdaptyProfile.appliedAttributionSources`, AA attribution'ın ne zaman uygulandığını size bildirir. ## Başlamadan önce \{#before-you-start\} İhtiyacınız olanlar: - Adapty React Native SDK **3.17.1** veya üzeri. - Adapty'de uygulama için yapılandırılmış Apple Ads. Bkz. [Apple Ads](apple-search-ads). ## Nasıl çalışır \{#how-it-works\} `adapty.activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution verisi talep eder ve sonucu Adapty'nin backend'ine iletir. AA, profil için etkin attribution kaynağı haline geldiğinde SDK, `onLatestProfileLoad` dinleyicinize güncellenmiş bir `AdaptyProfile` gönderir; bu profilin `appliedAttributionSources` dizisinde `'apple_search_ads'` yer alır. Bu sayede paywall'ı iki adımda yükleyebilirsiniz: 1. Hemen `getPaywall` çağırın. Henüz attribution uygulanmadığından Adapty, isteği varsayılan kitleye göre çözümler ve kullanıcı hemen bir paywall görür. 2. `'apple_search_ads'` göründüğünde tekrar `getPaywall` çağırın. Adapty bu sefer isteği Apple Ads kitlesine göre çözümler ve hedeflenmiş paywallı döndürür; bu paywall ilkinin yerini alır. `appliedAttributionSources` boş ya da eksik olabilir. Bu şu anlama gelir: - Bu profil için Apple Ads attribution'ı henüz işlenmemiştir, ya da - hiç attribution gelmemiştir. Her iki durumda da 1. adım güvenlidir — Adapty, isteği mevcut profil durumuna uyan kitleyle (genellikle varsayılan kitle) çözümler. 2. adım yalnızca `'apple_search_ads'` göründüğünde çalışır. :::important Sonraki her başlatmada, önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `'apple_search_ads'` taşır; dolayısıyla ilk `getPaywall` çağrısı doğrudan Apple Ads segmentine göre paywall'ı döndürür — ikinci bir istek veya görünür bir değişiklik olmaz. İki adımlı flow yalnızca attribution henüz işlenirken, yani ilk başlatmada önem taşır. ::: ## Uygulama \{#implementation\} Hemen bir paywall göster, ardından `'apple_search_ads'` olayını dinle ve geldiğinde paywall'ı yenile. 1. **SDK'yı etkinleştirin.** Bkz. [React Native SDK'yı yükleyin ve yapılandırın](sdk-installation-reactnative). 2. **Bir paywall yükleyin ve gösterin** — `getPaywall` ile her zamanki gibi yapın, attribution için beklemeyin. 3. **Profil güncellemelerine abone olun** — `adapty.addEventListener('onLatestProfileLoad', …)` ile `'apple_search_ads'` değerini takip edin. Bu değer göründüğünde, paywall'u tekrar çekip güncellenmiş olanı gösterin. Listener'ı henüz kurmadıysanız bkz. [Abonelik güncellemelerini dinleyin](react-native-check-subscription-status#listen-to-subscription-updates): ```typescript const subscription = adapty.addEventListener('onLatestProfileLoad', async profile => { if (!profile.appliedAttributionSources?.includes('apple_search_ads')) return; const targeted = await adapty.getPaywall(placementId); // present the targeted paywall in place of the first one }); // Call subscription.remove() after the upgrade, or after a timeout (see below). ``` 4. **Zaman aşımından sonra dinlemeyi durdurun.** Kullanıcıların büyük çoğunluğu Apple Ads attribution'ı hiçbir zaman almaz; bu nedenle dinleyiciyi tüm oturum boyunca açık tutmak yerine bir süre sonra kaldırın. İstek başarısız olduğunda kullanıcının her zaman bir şey görmesi için placement'a bir [yedek paywall](react-native-use-fallback-paywalls) yapılandırın. ## Eksiksiz örnek \{#complete-example\} `onAppleAdsAttribution`, Apple Ads attribution uygulandığında çözümlenir ya da `timeoutMs` süresi geçince reddedilir. Aşağıdaki kullanımda paywall hemen yüklenir, ardından attribution geldiğinde yeniden çekilir — Apple Ads kullanıcıları hedefli paywall'ı görür; attribution hiç gelmezse ilk paywall yerinde kalır: ```typescript const APPLE_ADS_SOURCE = 'apple_search_ads'; const placementId = 'YOUR_PLACEMENT_ID'; function hasAppleAdsAttribution(profile: AdaptyProfile): boolean { return profile.appliedAttributionSources?.includes(APPLE_ADS_SOURCE) ?? false; } /** * Resolves once Apple Ads attribution is applied to the profile. * Rejects with a timeout error if attribution never arrives within `timeoutMs`. * Call after `adapty.activate()`. */ export function onAppleAdsAttribution(timeoutMs: number): Promise<void> { return new Promise((resolve, reject) => { let timer: ReturnType<typeof setTimeout> | undefined; let subscription: { remove: () => void } | undefined; const stop = () => { clearTimeout(timer); subscription?.remove(); }; subscription = adapty.addEventListener('onLatestProfileLoad', profile => { if (!hasAppleAdsAttribution(profile)) return; stop(); resolve(); }); timer = setTimeout(() => { stop(); reject(new Error(`Apple Ads attribution timed out after ${timeoutMs}ms`)); }, timeoutMs); }); } let paywall = await adapty.getPaywall(placementId); onAppleAdsAttribution(30_000) .then(() => adapty.getPaywall(placementId)) .then(updated => { paywall = updated; }) .catch(() => { console.log('Apple Ads attribution or loading failed'); }); ``` İlk açılışta Apple Ads kullanıcıları, varsayılan paywall'un değiştirilmeden önce kısa süreliğine görünmesine tanık olabilir. Paywall'ları Paywall Builder ile sunuyorsanız, yeniden sunumun kabul edilebilir olup olmadığına karar verin ya da güncellemeyi yalnızca paywall gösterilmeden önce uygulayın. `timeoutMs` değerini ne kadar süre dinlemeye hazır olduğunuza göre ayarlayın — gelen attribution verisi genellikle uygulamanın açılmasından sonraki birkaç saniye içinde ulaşır. Uygulamanız başka amaçlarla zaten `onLatestProfileLoad` dinliyorsa (örneğin, [abonelik durumunu kontrol etmek](react-native-check-subscription-status#listen-to-subscription-updates) için), bunu değiştirmenize gerek yok. `adapty.addEventListener` birden fazla bağımsız dinleyiciyi destekler, dolayısıyla bu kendi dinleyicisini mevcut olanları etkilemeden ekler. --- # File: react-native-test --- --- title: "React Native SDK'da Test & Yayına Alma" description: "Adapty SDK ile React Native uygulamanızı nasıl test edip yayınlayacağınızı öğrenin." --- Adapty SDK'yı React Native uygulamanıza entegre ettiyseniz, her şeyin doğru kurulduğunu ve satın almaların hem iOS hem de Android platformlarında beklendiği gibi çalıştığını test etmek isteyeceksinizdir. Bu süreç; SDK entegrasyonunun ve Apple'ın sandbox ortamı ile Google Play'in test ortamında gerçek satın alma akışının test edilmesini kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almalarınızı kapsamlı şekilde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayına almaya hazırlık \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce aşağıdakileri doğrulamak için [Yayın kontrol listesi](release-checklist)'ni takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış olmalı - Satın almalar tamamlanıp Adapty'ye raporlanmalı - Erişim doğru şekilde açılıp geri yüklenebilmeli - Gizlilik ve inceleme gereksinimleri karşılanmış olmalı --- # File: InvalidProductIdentifiers-react-native --- --- title: "React Native SDK'da Code-1000 noProductIDsFound Hatasının Çözümü" description: "Adapty'de abonelikleri yönetirken geçersiz ürün tanımlayıcısı hatalarını çözün." --- 1000 kodlu `noProductIDsFound` hatası, paywallda talep ettiğiniz ürünlerin App Store'da listelenmiş olmalarına rağmen satın alma için mevcut olmadığını gösterir. Bu hata bazen `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız tek başına görünüyorsa, güvenle yoksayabilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız, çözmek için şu adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin \{#step-3-check-products\} 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne geçin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümü altında göreceksiniz. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Tablodaki ürün ID'sini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesindekiyle karşılaştırın. ID'ler eşleşmiyorsa, tablodaki ürün ID'sini kopyalayın ve Adapty Kontrol Paneli'nde bununla bir [ürün oluşturun](create-product). <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** bölümüne kaydırın ve gerekli tüm ülke ve bölgelerin listelendiğini kontrol edin. <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'te tekrar **Monetization** → **Subscriptions** bölümüne gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** bölümüne kaydırın ve **Current Pricing for New Subscribers** bölümünü genişletin. <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Gerekli tüm fiyatların listelendiğinden emin olun. <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. Uygulamanın ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) ana sayfasında **Business** seçeneğine tıklayın. <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şirket adınızı seçin. 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** alanlarının tümünün **Active** olarak göründüğünü doğrulayın. Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayına alabilirsiniz. ## Adım 6. Ürün takılıp kaldıysa yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5 arası adımların hepsi geçebilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — ama SDK yine de `1000 noProductIDsFound` hatası döndürebilir. Bu durumda ürün Apple'ın kayıt defterinde takılı kalmış olabilir. Apple'ın ürün kayıt defteri zaman zaman öyle bir duruma girer ki ürün App Store Connect arayüzünde görünür ama StoreKit arama yoluna açık değildir. Ürünü App Store Connect'ten silip aynı ürün ID'siyle yeniden oluşturun. Yeniden oluşturmanın ardından yayılması için 24 saate kadar bekleyin. --- # File: cantMakePayments-react-native --- --- title: "React Native SDK'da Code-1003 cantMakePayment hatasının çözümü" description: "Adapty'de abonelikleri yönetirken oluşan ödeme yapılamıyor hatasını çözün." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: migration-to-react-native-sdk-v4 --- --- title: "Adapty React Native SDK'yı v. 4.0'a geçirme" description: "Paywall API'lerini flow API'leriyle değiştirerek Adapty React Native SDK v4.0 (beta) sürümüne geçin — hem Flow Builder hem de Paywall Builder ile uyumludur." --- Adapty React Native SDK 4.0 (beta), flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez. ## Hızlı başvuru \{#quick-reference\} | v3 | v4 | |---|---| | `adapty.getPaywall(placementId, locale?, params?)` | `adapty.getFlow(placementId, params?)` | | `adapty.getPaywallForDefaultAudience(placementId, locale?, params?)` | `adapty.getFlowForDefaultAudience(placementId, params?)` | | `adapty.getPaywallProducts(paywall)` | `adapty.getPaywallProducts(flow)` | | `adapty.logShowPaywall(paywall)` | `adapty.logShowFlow(flow)` | | `AdaptyPaywall` (tür) | `AdaptyFlow` | | `createPaywallView(paywall)` | `createFlowView(flow)` | | `AdaptyPaywallView` (bileşen) | `AdaptyFlowView` | | `EventHandlers` (tür) | `FlowEventHandlers` | | `onPaywallShown` | `onAppeared` | | `onPaywallClosed` | `onDisappeared` | | `onRenderingFailed` | `onError` | `AdaptyPaywallProduct` adını korur — ürünler hâlâ bir flow'a aittir ve `getPaywallProducts` artık bir `AdaptyFlow` alır. `getFlow` ve `getFlowForDefaultAudience` metodları artık `locale` parametresi almaz. `present`, `dismiss`, `setEventHandlers` ve `showDialog` view metodları ile `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` ve `onAndroidSystemBack` olay işleyicileri v3 ile aynı adları korur. Bazı varsayılan davranışlar değişti — bkz. [Varsayılan davranış değişiklikleri](#default-behavior-changes). ## Minimum iOS sürümü \{#minimum-ios-version\} Adapty React Native SDK 4.0, minimum iOS dağıtım hedefini iOS 13.0'dan **iOS 15.0**'a yükseltir. Yükseltmeden önce iOS dağıtım hedefinizi 15.0 veya sonrasına ayarlayın. ## Kurulum \{#installation\} ### Paketi güncelleyin \{#update-the-package\} v4.0 bir ön sürümdür, bu yüzden tam sürümü sabitleyin — npm, caret/tilde aralıkları üzerinden ön sürümleri seçmez: ```bash showLineNumbers npm install react-native-adapty@4.0.0 # or yarn add react-native-adapty@4.0.0 ``` ### iOS: Yerel SDK'lar artık Swift Package Manager üzerinden geliyor \{#ios-native-sdks-now-come-through-swift-package-manager\} [CocoaPods'un spec deposu Aralık 2026'da salt okunur hale geliyor](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), bu nedenle v4 itibarıyla yerel `Adapty`, `AdaptyUI` ve `AdaptyPlugin` SDK'ları **artık CocoaPods alt bağımlılığı olarak çekilmiyor** — podspec bunları **Swift Package Manager** üzerinden çekiyor (`spm_dependency` yardımcısı aracılığıyla). Bunun için iki şey gerekiyor: - **React Native 0.75 veya üstü** — `spm_dependency` podspec yardımcısı için gereklidir. Daha eski bir sürümde `pod install` açık bir hata ile başarısız olur; önce React Native'i güncelleyin ya da `react-native-adapty` 3.x sürümünde kalın. - **Dinamik framework'ler** — SPM bağımlılıkları dinamik bağlantı gerektirir. Bunu nasıl etkinleştireceğiniz Expo ve bare React Native için farklıdır. #### Expo [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/) config plugin'ini ekleyin ve `app.json` (veya `app.config.js`) dosyasında iOS framework'lerini dinamik olarak ayarlayın: ```json showLineNumbers title="app.json" { "expo": { "plugins": [ [ "expo-build-properties", { "ios": { "useFrameworks": "dynamic" } } ] ] } } ``` Ardından eklentiyi yükleyin ve native projeyi yeniden oluşturun: ```bash showLineNumbers npx expo install expo-build-properties npx expo prebuild --clean ``` #### Bare React Native \{#bare-react-native\} iOS hedefinize dinamik framework'leri ekleyin, ardından pod'ları yeniden yükleyin: ```ruby showLineNumbers title="ios/Podfile" use_frameworks! :linkage => :dynamic ``` ```bash showLineNumbers cd ios && pod install --repo-update ``` Daha önce `Adapty`, `AdaptyUI` veya `AdaptyPlugin`'i CocoaPods alt bağımlılığı olarak çektiyseniz, önce `Podfile` dosyanızdaki açık `pod 'Adapty'`, `pod 'AdaptyUI'` veya `pod 'AdaptyPlugin'` satırlarını kaldırın. :::warning Varsayılan statik bağlamadan dinamik framework'lere geçiş, modüler başlıkları henüz desteklemeyen kütüphanelerle çakışabilir ve Flipper ile uyumsuz olabilir. Derleme sorunlarıyla karşılaşırsanız, şu kaynağa bakın: [Swift Package Manager'ı React Native kütüphaneleriyle entegre etme](https://www.callstack.com/blog/integrating-swift-package-manager-with-react-native-libraries). ::: Tam kurulum için [Adapty SDK'yı Yükle](sdk-installation-reactnative) sayfasına bakın. ## Flow'ları getirme \{#fetching-flows\} ### getPaywall → getFlow Döndürülen tür `AdaptyPaywall`'dan `AdaptyFlow`'a değişiyor ve `locale` parametresi kaldırılıyor — bir flow render ederken locale otomatik olarak belirlenir; özel paywalllar için tüm locale'ler `flow.remoteConfigs` içinde döner: ```diff showLineNumbers - const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID', 'en'); + const flow = await adapty.getFlow('YOUR_PLACEMENT_ID'); ``` `getPaywallForDefaultAudience` da aynı şekilde yeniden adlandırıldı: ```diff showLineNumbers - const paywall = await adapty.getPaywallForDefaultAudience('YOUR_PLACEMENT_ID', 'en'); + const flow = await adapty.getFlowForDefaultAudience('YOUR_PLACEMENT_ID'); ``` ### getPaywallProducts(paywall) → getPaywallProducts(flow) `getPaywallProducts` adını korur ancak artık bir `AdaptyFlow` alır: ```diff showLineNumbers - const products = await adapty.getPaywallProducts(paywall); + const products = await adapty.getPaywallProducts(flow); ``` ## Veri modeli \{#data-model\} `getFlow`, `AdaptyPaywall` yerine bir `AdaptyFlow` döndürür ve nesne yapısı değişti: | v3 `AdaptyPaywall` alanı | v4 `AdaptyFlow` alanı | İşlem | |---|---|---| | `remoteConfig?` (tek) | `remoteConfigs?: AdaptyRemoteConfig[]` (dizi) | Bir flow, yapılandırılmış her dil için bir remote config taşır. Kullanıcıyla eşleşeni okuyun: `flow.remoteConfigs?.find((c) => c.lang === 'en')`. | | `products` | `flow.paywalls[i].productIdentifiers` | Ürün tanımlayıcıları artık flow'da değil, her flow varyasyonunda yer alır. | | `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Flow'dan her paywall varyasyonuna taşındı. | | `version?: number` | `flowVersionId?: string` | Yeniden adlandırıldı ve tür `number`'dan `string`'e değiştirildi. | | `hasViewConfiguration` | kaldırıldı | Kodunuzdaki tüm `hasViewConfiguration` kontrollerini kaldırın. | | `requestLocale` | kaldırıldı | Dil artık modelin bir parçası değil. | | _(yeni)_ | `paywalls: AdaptyFlowPaywall[]` | Her giriş, flow içindeki bir paywall varyasyonudur. | | _(yeni)_ | `responseCreatedAt: number` | Sunucu yanıt zaman damgası, milisaniye cinsinden. | Ürün tanımlayıcıları flow'dan her varyasyona taşındı: ```diff showLineNumbers - const ids = paywall.products; + const ids = flow.paywalls[0].productIdentifiers; ``` ## Web paywall metotları \{#web-paywall-methods\} `openWebPaywall` ve `createWebPaywallUrl` adlarını korur, ancak ilk argüman artık `AdaptyPaywall` yerine bir `AdaptyFlowPaywall`'dır (bir flow varyasyonu). Yine de bir `AdaptyPaywallProduct` geçirebilirsiniz. ```diff showLineNumbers const flow = await adapty.getFlow('YOUR_PLACEMENT_ID'); - await adapty.openWebPaywall(paywall); + await adapty.openWebPaywall(flow.paywalls[0]); ``` ## Flow görüntülemelerini izleme \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık bir `AdaptyFlow` alır. Olay hâlâ aynı varyasyona kaydedilir, dolayısıyla mevcut huni ve A/B testi metrikleri kontrol paneli değişiklikleri olmadan çalışmaya devam eder. ```diff showLineNumbers - await adapty.logShowPaywall(paywall); + await adapty.logShowFlow(flow); ``` v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından render edilen flow'ları ya da paywall'ları görüntülerken bu metodu çağırmanız gerekmez — Adapty bu görüntülemeleri otomatik olarak izler. ## Flow'ları görüntüleme \{#displaying-flows\} ### createPaywallView → createFlowView Fabrika fonksiyonunu yeniden adlandırın ve `AdaptyFlow`'u geçirin. Dönen denetleyicinin metotları (`present`, `dismiss`, `setEventHandlers`, `showDialog`) değişmedi: ```diff showLineNumbers - import { createPaywallView } from 'react-native-adapty'; + import { createFlowView } from 'react-native-adapty'; - const view = await createPaywallView(paywall); + const view = await createFlowView(flow); await view.present(); ``` ### AdaptyPaywallView → AdaptyFlowView React bileşeniyle render ediyorsanız, bileşeni yeniden adlandırın ve `flow` prop'unu geçin: ```diff showLineNumbers - import { AdaptyPaywallView } from 'react-native-adapty'; + import { AdaptyFlowView } from 'react-native-adapty'; - <AdaptyPaywallView paywall={paywall} /* … */ /> + <AdaptyFlowView flow={flow} /* … */ /> ``` :::note `createFlowView` ile oluşturulan bir flow görünümü tek kullanımlıktır: `dismiss()` çağrıldıktan sonra görünüm yok edilir, bu nedenle flow'u tekrar göstermek için `createFlowView`'i yeniden çağırmanız gerekir. Gömülü bir `AdaptyFlowView` ise unmount edilerek kapatılır — bir handler'dan `true` döndürmek gömülü görünümü kapatmaz, bunun yerine kendi state'inizi değiştirmeniz gerekir; örneğin `onCloseButtonPress` içinde bunu yapabilirsiniz. ::: ## Olayları yönetme \{#handling-events\} Olay işleyici arayüzü `EventHandlers`'dan `FlowEventHandlers`'a yeniden adlandırıldı ve üç callback yeniden adlandırıldı. Mevcut işleyici gövdelerinde kod değişikliği gerekmez — yalnızca yeniden adlandırın: ```diff showLineNumbers - onPaywallShown: () => { /* … */ }, + onAppeared: () => { /* … */ }, - onPaywallClosed: () => { /* … */ }, + onDisappeared: () => { /* … */ }, - onRenderingFailed: (error) => { /* … */ }, + onError: (error) => { /* … */ }, ``` Diğer tüm olay işleyiciler isimlerini korur. İkisi ayrıca ikinci bir argüman kazanır: `onPurchaseCompleted` artık `(purchaseResult, product)` ve `onPurchaseFailed` artık `(error, product)` şeklindedir; burada `product`, ilgili `AdaptyPaywallProduct`'tır. Tam liste için bkz. [Flow & paywall olaylarını yönetme](react-native-handling-events-1). :::note `onDisappeared` yalnızca `createFlowView().present()` ile modal olarak sunulan bir flow için tetiklenir. `AdaptyFlowView` bileşeni bunu prop olarak sunmaz — gömülü bir görünümü kapatmak için bileşeni unmount edin. ::: v4 ayrıca isteğe bağlı olarak kullanabileceğiniz birkaç yeni özellik ekler: - `adapty.openWebUrl(url, openIn?)` ve `adapty.requestAppReview()` metodları — bunlar varsayılan `onUrlPress` ve `onRequestAppReview` işleyicilerini destekler; böylece URL'ler ve uygulama değerlendirme istekleri kutudan çıktığı gibi yerel olarak işlenir. Bu işleyicileri geçersiz kılıyorsanız doğrudan çağırın. - Flow'lar içinde observer modunda satın alma işlemi için yeni `onObserverPurchaseInitiated` / `onObserverRestoreInitiated` işleyicileri. Bkz. [Observer modunda satın almaları yönetme](react-native-handling-events-1#handle-purchases-in-observer-mode). ## Kaldırılan ve kullanımdan kaldırılan API'ler \{#removed-and-deprecated-apis\} ### setFallbackPaywalls → setFallback `setFallbackPaywalls` kaldırıldı. Aynı argümanı alan `setFallback`'i kullanın: ```diff showLineNumbers - await adapty.setFallbackPaywalls(fileLocation); + await adapty.setFallback(fileLocation); ``` ### Kaldırılan dışa aktarımlar \{#removed-exports\} Bu semboller artık `react-native-adapty`'den dışa aktarılmıyor. İçe aktarımlarını kaldırın: - **`AdaptyPaywall`**: Bunun yerine `AdaptyFlow` kullanın. - **`ProductReference`**: `AdaptyProductIdentifier` kullanın; `flow.paywalls[i].productIdentifiers`'tan okuyun. - **`AdaptyPaywallBuilder`**: Kaldırıldı. Flow'lar ve paywall'lar yerel olarak render edilir. - **`AdaptyAndroidSubscriptionUpdateParameters`**: İç içe `subscriptionUpdateParams` yapısını kullanın (aşağıya bakın). ### activate: lockMethodsUntilReady `lockMethodsUntilReady` kaldırıldı ve bu davranış artık her zaman etkin. `activate` çağrınızdan kaldırın — bırakmanız durumunda artık derlenmez: ```diff showLineNumbers - await adapty.activate('PUBLIC_SDK_KEY', { lockMethodsUntilReady: true }); + await adapty.activate('PUBLIC_SDK_KEY'); ``` ### makePurchase: Android abonelik güncellemesi \{#makepurchase-android-subscription-update\} Düz Android abonelik güncelleme yapısı kaldırıldı. `oldSubVendorProductId` ve `prorationMode` değerlerini iç içe bir `subscriptionUpdateParams` nesnesine taşıyın ve `isOfferPersonalized`'ı üst düzeyde tutun. Tam örnek için bkz. [Satın alma işlemleri](react-native-making-purchases). ### Android: güvenli alan dolguları \{#android-safe-area-paddings\} Android boolean kaynağı `<bool name="adapty_paywall_enable_safe_area_paddings">…</bool>` kaldırıldı. Bunu `res/values/bools.xml`'den silin ve güvenli alan dolgularını çalışma zamanında, flow view'i oluştururken `enableSafeArea` parametresiyle kontrol edin. Modal sunum için varsayılan olarak `true`, gömülü bileşen için `false` değerini alır. ### Mock modu \{#mock-mode\} SDK'yı mock modunda (Expo Go veya web önizlemesi) çalıştırıyorsanız, mock yapılandırma anahtarı `paywalls`'ı `flows` olarak yeniden adlandırın. ## Varsayılan davranış değişiklikleri \{#default-behavior-changes\} Bu değişiklikler derleme hatası oluşturmaz; bu nedenle çalışma zamanında test edin: - **`onAndroidSystemBack`**: Varsayılan davranış, görünümü kapatmaktan açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `true` döndürün. - **`onPurchaseCompleted`**: Varsayılan davranış, görünümü kapatmaktan (kullanıcı satın almayı iptal etmedikçe) her zaman açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `purchaseResult.type !== 'user_cancelled'` döndürün. - **`onRestoreCompleted`**: Varsayılan davranış, başarılı bir geri yüklemeden sonra görünümü kapatmaktan açık tutmaya değişti. Önceki davranışı geri yüklemek için handler'dan `true` döndürün. - **`onUrlPress`**: Varsayılan davranış artık URL'yi kontrol panelindeki uygulama içi veya harici tarayıcı ayarını dikkate alarak yerel katman üzerinden açıyor. URL'leri kendiniz açmak için handler'ı geçersiz kılın. ## Onboarding API'sinin kullanımdan kaldırılması \{#onboarding-api-deprecation\} Eski onboarding API'si, v4.0'da [Flow Builder](adapty-flow-builder) lehine kullanımdan kaldırıldı. Hâlâ çalışıyor ve IDE'niz kullanımdan kaldırılan sembolleri `@deprecated` ek açıklamaları aracılığıyla işaretler — çalışma zamanı uyarısı yoktur. Bu semboller gelecekteki bir sürümde kaldırılacak, bu yüzden onboarding'lerinizi Flow Builder'a taşımayı planlayın. Kullanımdan kaldırılan semboller: `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView` ve `AdaptyOnboardingView`. --- # File: migration-react-native-314 --- --- title: "Adapty React Native SDK'yı v3.14'e Taşıyın" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty React Native SDK v3.14'e geçin." --- Adapty React Native SDK 3.14.0, sizin tarafınızda geçiş adımları gerektiren iyileştirmeler sunan büyük bir sürümdür: - `registerEventHandlers` metodu, `setEventHandlers` metoduyla değiştirildi. - `AdaptyOnboardingView` bileşeninde, event handler'lar artık bir `eventHandlers` nesnesi yerine ayrı prop'lar olarak aktarılıyor. - UI bileşenleri için yeni, basitleştirilmiş bir import stili getirildi. - `logShowOnboarding` metodu kaldırıldı. - Minimum React Native sürümü 0.73.0 olarak güncellendi. - Paywall'lar ve onboarding'ler için varsayılan iOS sunum stili, sayfa sayfasından tam ekrana değiştirildi. ## `registerEventHandlers`'ı `setEventHandlers` ile Değiştirin \{#replace-registereventhandlers-with-seteventhandlers\} Adapty Paywall ve Onboarding Builder ile çalışmak için kullanılan `registerEventHandlers` metodu, `setEventHandlers` metoduyla değiştirildi. Adapty Paywall Builder ve/veya Adapty Onboarding Builder kullanıyorsanız, uygulama kodunuzda `registerEventHandlers` ifadesini bulun ve `setEventHandlers` ile değiştirin. Bu değişiklik, metodun davranışını daha anlaşılır hale getirmek amacıyla yapıldı: Handler'lar artık tek tek çalışıyor çünkü her biri `true`/`false` döndürüyor; tek bir event için birden fazla handler tanımlamak sonuçtaki davranışı belirsiz hale getiriyordu. `AdaptyOnboardingView` veya `AdaptyPaywallView` gibi React bileşenleri kullanırken event handler'lardan `true`/`false` döndürmeniz gerekmez; bileşenin görünürlüğünü kendi state yönetiminiz aracılığıyla kontrol edersiniz. Dönüş değerleri yalnızca SDK'nın view yaşam döngüsünü yönettiği modal ekran sunumlarında gereklidir. :::important `setEventHandlers`'ı birden fazla kez çağırmak, sağladığınız handler'ların üzerine yazar; bu, ilgili event'ler için hem varsayılan hem de önceden ayarlanan handler'ların yerini alır. ::: ```diff showLineNumbers - const unsubscribe = view.registerEventHandlers({ - // your event handlers - }) const unsubscribe = view.setEventHandlers({ // your event handlers }) ``` ## UI Bileşenleri için Import Yollarını Güncelleyin \{#update-import-paths-for-ui-components\} Adapty SDK 3.14.0, UI bileşenleri için basitleştirilmiş bir import stili sunuyor. Artık `react-native-adapty/dist/ui` yerine doğrudan `react-native-adapty`'den import edebilirsiniz. Yeni import stili, standart React Native pratikleriyle daha tutarlı ve import ifadelerini daha sade hale getiriyor. `AdaptyPaywallView` veya `AdaptyOnboardingView` gibi UI bileşenleri kullanıyorsanız, import'larınızı aşağıda gösterildiği gibi güncelleyin: ```diff showLineNumbers - import { AdaptyPaywallView } from 'react-native-adapty/dist/ui'; + import { AdaptyPaywallView } from 'react-native-adapty'; - import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui'; + import { AdaptyOnboardingView } from 'react-native-adapty'; - import { createPaywallView } from 'react-native-adapty/dist/ui'; + import { createPaywallView } from 'react-native-adapty'; - import { createOnboardingView } from 'react-native-adapty/dist/ui'; + import { createOnboardingView } from 'react-native-adapty'; ``` :::note Geriye dönük uyumluluk için eski import stili (`react-native-adapty/dist/ui`) hâlâ desteklenmektedir. Ancak tutarlılık ve netlik açısından yeni import stilini kullanmanızı öneririz. ::: ## React Bileşeninde Onboarding Event Handler'larını Güncelleyin \{#update-onboarding-event-handlers-in-the-react-component\} Onboarding'lere ait event handler'lar, `AdaptyOnboardingView`'daki `eventHandlers` nesnesinin dışına taşındı. Onboarding'leri `AdaptyOnboardingView` kullanarak gösteriyorsanız, event handling yapısını güncelleyin. :::important Event handler'ları uygularken önerilen yönteme dikkat edin. Her render'da nesnelerin yeniden oluşturulmasını önlemek için event handler fonksiyonlarında `useCallback` kullanın. ::: ```diff showLineNumbers import React, { useCallback } from 'react'; - import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui'; + import { AdaptyOnboardingView } from 'react-native-adapty'; + import type { OnboardingEventHandlers } from 'react-native-adapty'; + + function MyOnboarding({ onboarding }) { + const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); + const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); + const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); + const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); + const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); + const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); + const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); + return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} - eventHandlers={{ - onAnalytics(event, meta) { /* ... */ }, - onClose(actionId, meta) { /* ... */ }, - onCustom(actionId, meta) { /* ... */ }, - onPaywall(actionId, meta) { /* ... */ }, - onStateUpdated(action, meta) { /* ... */ }, - onFinishedLoading(meta) { /* ... */ }, - onError(error) { /* ... */ }, - }} + onAnalytics={onAnalytics} + onClose={onClose} + onCustom={onCustom} + onPaywall={onPaywall} + onStateUpdated={onStateUpdated} + onFinishedLoading={onFinishedLoading} + onError={onError} /> ); + } ``` :::note Geriye dönük uyumluluk için `eventHandlers` prop'u hâlâ desteklenmektedir ancak kullanımdan kaldırılmıştır. Yukarıda gösterildiği gibi ayrı event handler prop'larına geçmenizi öneririz. ::: ## `logShowOnboarding`'i Kaldırın \{#delete-logshowonboarding\} Adapty SDK 3.14.0'da `logShowOnboarding` metodu SDK'dan kaldırıldı. Bu metodu kullanıyorsanız, SDK'yı 3.14 veya sonraki bir sürüme yükselttiğinizde artık kullanılamaz. Bunun yerine [Adapty kodsuz onboarding builder'da onboarding'ler oluşturabilirsiniz](onboardings). Bu onboarding'lere ait analizler otomatik olarak takip edilir ve pek çok özelleştirme seçeneğine sahip olursunuz. ## React Native'i Güncelleyin \{#update-react-native\} Adapty SDK 3.14.0'dan itibaren React Native'in desteklenen minimum sürümü 0.73.0'dır. Daha eski bir sürüm kullanıyorsanız, Adapty SDK ile tutarlı ve güvenilir bir deneyim için React Native'i 0.73.0 veya sonraki bir sürüme güncelleyin. ## Modal Paywall'lar ve Onboarding'ler için iOS Sunum Stilini Güncelleyin \{#update-ios-presentation-style-for-modal-paywalls-and-onboardings\} Adapty SDK 3.14.0'da, `view.present()` metodu kullanılarak görüntülenen paywall'lar ve onboarding'ler için varsayılan iOS sunum stili, sayfa sayfasından tam ekrana değiştirildi. Önceki sayfa sayfası sunum stilini korumak istiyorsanız, `present()` metoduna `iosPresentationStyle` parametresini geçin: ```typescript showLineNumbers title="React Native (TSX)" try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` --- # File: react-native-migration-guide-380 --- --- title: "Adapty React Native SDK'yı v3.8'e Geçirin" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty React Native SDK v3.8'e geçin." --- Adapty SDK 3.8.0, bazı iyileştirmeler içeren büyük bir sürümdür. Ancak bu iyileştirmeler, sizden bazı geçiş adımları gerektirebilir. ## Placement parametrelerini alma için giriş türünü güncelleyin \{#update-input-type-for-getting-placement-params\} `GetPaywallParamsInput`, `GetPlacementParamsInput` olarak yeniden adlandırıldı: ```diff showLineNumbers - type GetPaywallParamsInput = { + type GetPlacementParamsInput = { placementId: string; locale?: string; fetchPolicy?: AdaptyPlacementFetchPolicy; loadTimeoutMs?: number; } ``` ## Yedek yöntemi güncelleyin \{#update-fallback-method\} Yedekleri ayarlamak için kullanılan yöntem güncellendi ve yedek konumlarını belirtmek için kullanılan tür yeniden adlandırıldı: ```diff showLineNumbers - adapty.setFallbackPaywalls(paywallsLocation: Input.FallbackPaywallsLocation); + adapty.setFallback(fileLocation: Input.FileLocation); ``` ## Paywall özellik erişimini güncelleyin \{#update-paywall-property-access\} Aşağıdaki özellikler `AdaptyPaywall`'dan `AdaptyPlacement`'a taşındı: ```diff showLineNumbers - paywall.abTestName - paywall.audienceName - paywall.revision - paywall.placementId + paywall.placement.abTestName + paywall.placement.audienceName + paywall.placement.revision + paywall.placement.id ``` --- # File: migration-to-react-native-sdk-34 --- --- title: "Adapty React Native SDK'yı v3.4'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty React Native SDK v3.4'e geçin." --- Adapty SDK 3.4.0, sizin tarafınızda geçiş adımları gerektiren iyileştirmeler sunan büyük bir sürümdür. ## Yedek paywall dosyalarını güncelleme \{#update-fallback-paywall-files\} Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki [mevcut yedek paywall'ları yeni dosyalarla değiştirin](react-native-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleme \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Daha önce, işlemleri Adapty'ye bildirmek için farklı yöntemler kullanılıyordu. Yeni sürümde, `reportTransaction` yöntemi hem Android hem de iOS'ta tutarlı biçimde kullanılmalıdır. Bu yöntem, her işlemi Adapty'ye açıkça bildirir ve tanınmasını sağlar. Bir paywall kullanıldıysa, işlemi ona bağlamak için variation ID'yi iletin. :::warning **İşlem raporlamayı atlama!** `reportTransaction` çağırmazsanız Adapty işlemi tanımaz, analytics'te görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - if (Platform.OS === 'android') { - try { - await adapty.restorePurchases(); - } catch (error) { - // handle the error - } - } const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` --- # File: migration-to-react-native330 --- --- title: "Adapty React Native SDK'yı v3.3'e Taşı" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty React Native SDK v3.3'e geçiş yapın." --- Adapty SDK 3.3.1, bazı iyileştirmeler içeren önemli bir sürümdür ve sizden birkaç geçiş adımı gerektirebilir. 1. Adapty SDK v3.3.x sürümüne yükseltin. 2. Modelleri güncelleyin. 3. `getProductsIntroductoryOfferEligibility` metodunu kaldırın. 4. Satın alma işlemini güncelleyin. 5. Paywall Builder paywall sunumunu güncelleyin. 6. Geliştirici tanımlı zamanlayıcı uygulamasını gözden geçirin. 7. Paywall Builder satın alma olaylarının işlenmesini güncelleyin. 8. Paywall Builder özel eylem olaylarının işlenmesini güncelleyin. 9. `onProductSelected` geri çağırmasını değiştirin. 10. `updateProfile` metodundan üçüncü taraf entegrasyon parametrelerini kaldırın. 11. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal ve Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. 12. Observer mode uygulamasını güncelleyin. ## Adapty React Native SDK'yı 3.3.x Sürümüne Yükseltme \{#upgrade-adapty-react-native-sdk-to-33x\} 3.3.1 sürümünden önce, `react-native-adapty` SDK, Adapty'nin uygulamanızda düzgün çalışması için gerekli olan temel SDK'ydı. `@adapty/react-native-ui` SDK'sı ise isteğe bağlıydı ve yalnızca Adapty Paywall Builder kullanıyorsanız ihtiyaç duyuluyordu. 3.3.1 sürümünden itibaren `@adapty/react-native-ui` SDK'sı kullanımdan kaldırılmış olup işlevselliği `react-native-adapty` SDK'sına entegre edilmiştir. 3.3.1 sürümüne yükseltmek için aşağıdaki adımları izleyin: 1. `react-native-adapty` paketini 3.3.1 sürümüne güncelleyin. 2. `@adapty/react-native-ui` paketini proje bağımlılıklarınızdan kaldırın. 3. Değişiklikleri uygulamak için proje bağımlılıklarınızı senkronize edin. ## Modellerdeki değişiklikler \{#changes-in-models\} ### Yeni modeller \{#new-models\} 1. [AdaptySubscriptionOffer](https://react-native.adapty.io/interfaces/adaptysubscriptionoffer): ```typescript showLineNumbers export interface AdaptySubscriptionOffer { readonly identifier: AdaptySubscriptionOfferId; phases: AdaptyDiscountPhase[]; android?: { offerTags?: string[]; }; } ``` 2. [AdaptySubscriptionOfferId](https://react-native.adapty.io/types/adaptysubscriptionofferid): ```typescript showLineNumbers export type AdaptySubscriptionOfferId = | { id?: string; type: 'introductory'; } | { id: string; type: 'promotional' | 'win_back'; }; ``` ### Değiştirilen modeller \{#changed-models\} 1. [AdaptyPaywallProduct](https://react-native.adapty.io/interfaces/adaptypaywallproduct): - `subscriptionDetails` özelliği `subscription` olarak yeniden adlandırıldı. <p> </p> ```diff showLineNumbers - subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; ``` 2. [AdaptySubscriptionDetails](https://react-native.adapty.io/interfaces/adaptysubscriptiondetails): - `promotionalOffer` kaldırıldı. Artık promosyon teklifi, yalnızca mevcut olduğunda `offer` özelliği içinde iletilir. Bu durumda `offer?.identifier?.type` değeri `'promotional'` olacaktır. - `introductoryOfferEligibility` kaldırıldı (teklifler yalnızca kullanıcı uygunsa döndürülür). - `offerId` kaldırıldı. Teklif ID'si artık `AdaptySubscriptionOffer.identifier` içinde saklanır. - `offerTags`, `AdaptySubscriptionOffer.android` içine taşındı. <p> </p> ```diff showLineNumbers - introductoryOffers?: AdaptyDiscountPhase[]; + offer?: AdaptySubscriptionOffer; ios?: { - promotionalOffer?: AdaptyDiscountPhase; subscriptionGroupIdentifier?: string; }; android?: { - offerId?: string; basePlanId: string; - introductoryOfferEligibility: OfferEligibility; - offerTags?: string[]; renewalType?: 'prepaid' | 'autorenewable'; }; } ``` 3. [AdaptyDiscountPhase](https://react-native.adapty.io/interfaces/adaptydiscountphase): - `identifier` alanı `AdaptyDiscountPhase` modelinden kaldırıldı. Teklif tanımlayıcısı artık `AdaptySubscriptionOffer.identifier` içinde saklanıyor. <p> </p> ```diff showLineNumbers - ios?: { - readonly identifier?: string; - }; ``` ### Kaldırılan modeller \{#remove-models\} 1. `AttributionSource`: - Daha önce `AttributionSource`'un kullanıldığı yerlerde artık doğrudan string kullanılmaktadır. 2. `OfferEligibility`: - Bu model artık gerekli olmadığından kaldırılmıştır. Artık bir teklif yalnızca kullanıcı uygunsa döndürülmektedir. ## `getProductsIntroductoryOfferEligibility` metodunu kaldırma \{#remove-getproductsintroductoryoffereligibility-method\} Adapty SDK 3.3.1 öncesinde, ürün nesneleri kullanıcının uygun olup olmadığından bağımsız olarak her zaman teklifleri içeriyordu. Bu durum, teklifi kullanmadan önce uygunluğu manuel olarak kontrol etmenizi gerektiriyordu. 3.3.1 sürümünden itibaren ürün nesnesi, teklifleri yalnızca kullanıcı uygunsa içermektedir. Bu sayede bir teklif mevcutsa kullanıcının uygun olduğunu varsayabilirsiniz; bu da süreci basitleştirir. ## Satın alma işlemini güncelleme \{#update-making-purchase\} Önceki sürümlerde, iptal edilen ve bekleyen satın almalar hata olarak değerlendirilir ve sırasıyla `2: 'paymentCancelled'` ve `25: 'pendingPurchase'` kodları döndürülürdü. 3.3.1 sürümünden itibaren, iptal edilen ve bekleyen satın almalar artık başarılı sonuç olarak kabul edilmekte ve buna göre işleme alınması gerekmektedir: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` ## Paywall Builder paywall sunumunu güncelleme \{#update-paywall-builder-paywall-presentation\} Güncellenmiş örnekler için [React Native'de yeni Paywall Builder paywalllerini sunma](react-native-present-paywalls) belgelerine bakın. ```diff showLineNumbers - import { createPaywallView } from '@adapty/react-native-ui'; + import { createPaywallView } from 'react-native-adapty/dist/ui'; const view = await createPaywallView(paywall); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` ## Geliştirici tanımlı zamanlayıcı uygulamasını güncelleme \{#update-developer-defined-timer-implementation\} `timerInfo` parametresini `customTimers` olarak yeniden adlandırın: ```diff showLineNumbers - let timerInfo = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } + let customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } //and then you can pass it to createPaywallView as follows: - view = await createPaywallView(paywall, { timerInfo }) + view = await createPaywallView(paywall, { customTimers }) ``` ## Paywall Builder satın alma etkinliklerini değiştirme \{#modify-paywall-builder-purchase-events\} Daha önce: - İptal edilen satın almalar `onPurchaseCancelled` callback'ini tetikliyordu. - Beklemedeki satın almalar `25: 'pendingPurchase'` hata kodunu döndürüyordu. Artık: - Her ikisi de `onPurchaseCompleted` callback'i tarafından işleniyor. #### Geçiş adımları: \{#steps-to-migrate\} 1. `onPurchaseCancelled` callback'ini kaldırın. 2. `25: 'pendingPurchase'` için hata kodu işlemeyi kaldırın. 3. `onPurchaseCompleted` callback'ini güncelleyin: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ // ... other optional callbacks onPurchaseCompleted(purchaseResult, product) { switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; // highlight-start case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; // highlight-end } // highlight-start return purchaseResult.type !== 'user_cancelled'; // highlight-end }, }); ``` ## Paywall Builder özel eylem olaylarını değiştirme \{#modify-paywall-builder-custom-action-events\} Kaldırılan callback'ler: - `onAction` - `onCustomEvent` Eklenen callback: - Yeni `onCustomAction(actionId)` callback'i. Özel eylemler için bunu kullanın. ## `onProductSelected` callback'ini değiştirme \{#modify-onproductselected-callback\} Önceden `onProductSelected`, `product` nesnesini gerektiriyordu. Artık string olarak `productId` gerektirmektedir. ## `updateProfile` metodundan üçüncü taraf entegrasyon parametrelerini kaldırma \{#remove-third-party-integration-parameters-from-updateprofile-method\} Üçüncü taraf entegrasyon tanımlayıcıları artık `setIntegrationIdentifier` metodu kullanılarak ayarlanmaktadır. `updateProfile` metodu artık bunları kabul etmemektedir. ## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleme \{#update-third-party-integration-sdk-configuration\} Adapty React Native SDK 3.3.1 ve sonraki sürümlerle entegrasyonların düzgün çalışmasını sağlamak için aşağıdaki bölümlerde açıklandığı gibi SDK yapılandırmalarınızı güncelleyin. Ayrıca attribution tanımlayıcısını almak için `AttributionSource` kullandıysanız, gerekli tanımlayıcıyı string olarak sağlayacak şekilde kodunuzu değiştirin. ### Adjust Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. ```diff showLineNumbers import { Adjust, AdjustConfig } from "react-native-adjust"; import { adapty } from "react-native-adapty"; var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); + Adjust.getAdid((adid) => { + if (adid) + adapty.setIntegrationIdentifier("adjust_device_id", adid); + }); ``` ### AirBridge \{#airbridge\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge) bölümüne bakın. ```diff showLineNumbers import Airbridge from 'airbridge-react-native-sdk'; import { adapty } from 'react-native-adapty'; try { const deviceId = await Airbridge.state.deviceUUID(); - await adapty.updateProfile({ - airbridgeDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` ### Amplitude \{#amplitude\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import { adapty } from 'react-native-adapty'; try { - await adapty.updateProfile({ - amplitudeDeviceId: deviceId, - amplitudeUserId: userId, - }); + await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); + await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` ### AppMetrica Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AppMetrica entegrasyonunda SDK yapılandırması](appmetrica#sdk-configuration) sayfasına bakın. ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import AppMetrica, { DEVICE_ID_KEY, StartupParams, StartupParamsReason } from '@appmetrica/react-native-analytics'; // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceId = params?.deviceId if (deviceId) { try { - await adapty.updateProfile({ - appmetricaProfileId: 'YOUR_ADAPTY_CUSTOMER_USER_ID', - appmetricaDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); + await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_KEY]) ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) bölümüne bakın. ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import appsFlyer from 'react-native-appsflyer'; appsFlyer.onInstallConversionData(installData => { try { - const networkUserId = appsFlyer.getAppsFlyerUID(); - adapty.updateAttribution(installData, AttributionSource.AppsFlyer, networkUserId); + const uid = appsFlyer.getAppsFlyerUID(); + adapty.setIntegrationIdentifier("appsflyer_id", uid); + adapty.updateAttribution(installData, "appsflyer"); } catch (error) { // handle the error } }); // ... appsFlyer.initSdk(/*...*/); ``` ### Branch \{#branch\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırması](branch#connect-your-app-to-branch) bölümüne bakın. ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { - adapty.updateAttribution(params, AttributionSource.Branch); + adapty.updateAttribution(params, "branch"); }, }); ``` ### Facebook Ads Aşağıda gösterildiği gibi mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [Facebook Ads entegrasyonu için SDK yapılandırması](facebook-ads#connect-your-app-to-facebook-ads) bölümüne bakın. ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { AppEventsLogger } from 'react-native-fbsdk-next'; try { const anonymousId = await AppEventsLogger.getAnonymousID(); - await adapty.updateProfile({ - facebookAnonymousId: anonymousId, - }); + await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` ### Firebase ve Google Analytics \{#firebase-and-google-analytics\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers import analytics from '@react-native-firebase/analytics'; import { adapty } from 'react-native-adapty'; try { const appInstanceId = await analytics().getAppInstanceId(); - await adapty.updateProfile({ - firebaseAppInstanceId: appInstanceId, - }); + await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } catch (error) { // handle `AdaptyError` } ``` ### Mixpanel \{#mixpanel\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonu için SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { Mixpanel } from 'mixpanel-react-native'; // ... try { - await adapty.updateProfile({ - mixpanelUserId: mixpanelUserId, - }); + await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) bölümüne bakın. <Tabs groupId="current-os" queryString> <TabItem value="v5+" label="OneSignal SDK v5+ (güncel)" default> ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import OneSignal from 'react-native-onesignal'; OneSignal.User.pushSubscription.addEventListener('change', (subscription) => { const subscriptionId = subscription.current.id; if (subscriptionId) { - adapty.updateProfile({ - oneSignalSubscriptionId: subscriptionId, - }); + adapty.setIntegrationIdentifier("one_signal_subscription_id", subscriptionId); } }); ``` </TabItem> <TabItem value="pre-v5" label="OneSignal SDK v. 4.x'e kadar (eski)" default> ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import OneSignal from 'react-native-onesignal'; OneSignal.addSubscriptionObserver(event => { const playerId = event.to.userId; - adapty.updateProfile({ - oneSignalPlayerId: playerId, - }); + adapty.setIntegrationIdentifier("one_signal_player_id", playerId); }); ``` </TabItem> </Tabs> ### Pushwoosh \{#pushwoosh\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırması](pushwoosh#sdk-configuration) bölümüne bakın. ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import Pushwoosh from 'pushwoosh-react-native-plugin'; // ... try { - await adapty.updateProfile({ - pushwooshHWID: hwid, - }); + await adapty.setIntegrationIdentifier("pushwoosh_hwid", hwid); } catch (error) { // handle `AdaptyError` } ``` ## Observer mode uygulamanızı güncelleyin \{#update-observer-mode-implementation\} Paywall'ları işlemlere nasıl bağladığınızı güncelleyin. Daha önce `variationId`'yi atamak için `setVariationId` metodunu kullanıyordunuz. Artık yeni `reportTransaction` metodunu kullanarak işlemi kaydederken `variationId`'yi doğrudan dahil edebilirsiniz. [Observer mode'da paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode-react-native) sayfasındaki son kod örneğine bakın. :::warning İşlemi `reportTransaction` metoduyla kaydetmeyi unutmayın. Bu adımı atlarsanız Adapty işlemi tanımaz, access level vermez, analitiklere dahil etmez ve entegrasyonlara göndermez. Bu adım zorunludur! ::: :::note `reportTransaction` metodundaki parametre sırası, `setVariationId` metodundakinden farklıdır. ::: ```diff showLineNumbers const variationId = paywall.variationId; try { - await adapty.setVariationId(variationId, transactionId); + await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` --- # File: migration-to-react-native-sdk-v3 --- --- title: "Adapty React Native SDK'yı v3.0'a Taşıma" description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty React Native SDK v3.0'a geçiş yapın." --- Adapty SDK v3.0, no-code ve kullanıcı dostu bir paywall oluşturma aracının yeni sürümü olan [Adapty Paywall Builder](adapty-paywall-builder)'ın desteğini sunuyor. Maksimum esneklik ve zengin tasarım özellikleriyle paywall'larınız çok daha etkili ve kârlı hale gelecek. ## 3.0.1 sürümüne yükseltin \{#upgrade-to-version-301\} 1. Normalde yaptığınız gibi 3.0.1 sürümüne yükseltin. 2. Yedek paywall dosyalarını değiştirin: 1. En son sürümü Adapty Kontrol Paneli'nden [indirin](fallback-paywalls). 2. Dosyaları kullanıcının cihazında saklayın ve [burada](react-native-use-fallback-paywalls) açıklandığı gibi `.setFallbackPaywalls` metoduna aktarın. --- # End of Documentation _Generated on: 2026-07-24T13:02:34.415Z_ _Successfully processed: 45/45 files_ # TUTORIAL - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.418Z Total files: 277 --- # File: is-adapty-right-for-me --- --- title: "Adapty benim için doğru mu?" description: "Adapty'nin kullanım durumunuza nasıl uyduğunu öğrenin. İster yeni bir uygulama başlatıyor, ister geliri optimize ediyor, ister başka bir araçtan geçiş yapıyor olun — başlamak için burası doğru yer." --- Adapty, mobil uygulamalar için bir uygulama içi satın alma platformudur. Abonelikler, tek seferlik satın almalar ve consumable'ları — satın alma işleminden ve fiş doğrulamasından analitiğe, A/B testine ve entegrasyonlara kadar — yönetir. İşte Adapty'nin farklı senaryolarda nasıl çalıştığı. ## Uygulama içi satın almalarla yeni bir uygulama başlatıyorum \{#im-launching-a-new-app-with-in-app-purchases\} Abonelik, tek seferlik satın alma veya consumable satmayı planlıyor olun, Adapty tüm yığını kapsar: - **7 platform için SDK**: iOS, Android, React Native, Flutter, Unity, Kotlin Multiplatform ve Capacitor. - **Satın alma yönetimi**: Yenilemeli abonelikler ve yeniden deneme mantığı, tek seferlik satın almalar, consumable'lar ve fiş doğrulama — hepsi sizin adınıza yönetilir. - **Kodsuz paywall oluşturucu**: UI kodu yazmadan paywall tasarlayın ve yayınlayın. - **İlk günden itibaren analitik**: İlk kullanıcılarınız gelir gelmez geliri, denemeleri, dönüşümleri ve daha fazlasını takip edin. Başlamaya hazır mısınız? [Hızlı Başlangıç kılavuzunu](quickstart) takip edin. ## A/B testleri, analitik ve entegrasyonlar istiyorum \{#i-want-ab-tests-analytics-and-integrations\} Adapty, halihazırda işe yarayan şeyleri optimize etmenize yardımcı olur: - **A/B testi**: Neyin en iyi dönüşümü sağladığını bulmak için farklı fiyatları, paywall tasarımlarını, deneme sürelerini ve promosyon tekliflerini test edin. 20.000 abonelik uygulamasından elde edilen verilere dayalı, uygulamanıza özel A/B testi önerileri almak için [AI Growth Advisor](autopilot) kullanın. - **Analitik grafikler**: MRR, LTV, churn, retention ve düzinelerce başka metriği takip edin. - **Kitle segmentasyonu**: Belirli kullanıcı gruplarını özel paywall'lar ve tekliflerle hedefleyin. - **Uzaktan paywall yapılandırması**: Yeni bir uygulama sürümü yayınlamadan paywall'larınızı güncelleyin. - **Üçüncü taraf entegrasyonları**: Satın alma etkinliklerini Amplitude, AppsFlyer, Adjust, Mixpanel ve ekibinizin halihazırda kullandığı diğer araçlara gönderin. [A/B testi](ab-tests), [Analitik](analytics), [Analitik servis entegrasyonları](analytics-integration) veya [Attribution servis entegrasyonları](attribution-integration) bölümlerini inceleyin. ## Uygulama içi satın almaları bir LLM ile uygulamak istiyorum \{#i-want-to-implement-in-app-purchases-with-an-llm\} Adapty'nin dokümanları, Cursor, Claude, ChatGPT ve diğerleri gibi yapay zeka destekli kodlama asistanlarıyla kullanım için optimize edilmiştir. Her sayfa düz Markdown olarak mevcuttur ve her platform için adım adım LLM destekli uygulama kılavuzları sunuyoruz: - **Kopyala-yapıştır hazır kılavuzlar**: Kılavuzu LLM'inize gönderin ve her uygulama aşamasında size rehberlik etmesini sağlayın. - **Markdown erişimi**: Herhangi bir dokümantasyon URL'sine `.md` ekleyin veya temiz bir metin sürümü almak için **Copy for LLM** düğmesine tıklayın. - **Context7 MCP desteği**: Adapty dokümanlarını doğrudan LLM destekli IDE'nize bağlayın. Platformunuzu seçin ve başlayın: [Yapay zeka yardımıyla Adapty'yi entegre edin](adapty-cursor). ## Apple Ads kampanyaları yürütmek ve optimize etmek istiyorum \{#i-want-to-run-and-optimize-apple-ads-campaigns\} Apple Search Ads yürütüyorsanız, Adapty Ads Manager — herhangi bir MMP gerektirmeden — kampanya performansınızı doğrudan gelir metrikleriyle ilişkilendirir: - **Gerçek zamanlı performans verileri**: Kampanyaları, reklam gruplarını ve anahtar kelimeleri takip edin. - **Uçtan uca gelir takibi**: Aramadan yüklemeden denemeye, aboneliğe ve LTV'ye kadar zinciri takip edin. - **Yapay zeka tahminleri ve önerileri**: Getirileri tahmin edin ve ölçeklendirme önerileri alın. - **AI Agent**: Hesabınız hakkında sade dille sorular sorun ve tam dönüşüm hunisi yanıtları ile öneriler alın. - **Kural tabanlı otomasyonlar**: CPA ve ROAS hedeflerinizi istikrarlı tutun. [Adapty Ads Manager](adapty-ads-manager) ile başlayın. ## Kullanıcılarımın nereden geldiğini takip etmek istiyorum \{#i-want-to-track-where-my-users-come-from\} Adapty Attribution, reklam harcamalarını uygulama kurulumları ve abonelik gelirleriyle ilişkilendiren yerleşik bir attribution çözümüdür: - **Birleşik pazarlama panosu**: Tüm kanallarınızdaki ROAS, kurulum ve gelir verilerini tek bir yerden görün. - **Dahili attribution**: Harici MMP'lere gerek kalmadan reklam kampanyalarını kurulumlar ve gelirle ilişkilendirin. - **Takip bağlantıları**: Doğru attribution için Adapty'de bağlantılar oluşturun ve kampanyalarınıza ekleyin. - **Ertelenmiş deeplink'ler**: Kullanıcıları tıkladıklarında uygulamaya sahip olmasalar bile kurulumdan sonra doğru içeriğe yönlendirin. - **Kohort analizi**: Zaman içinde edinim performansını ve kullanıcı davranışını analiz edin. [Adapty Attribution](adapty-user-acquisition) hakkında daha fazla bilgi edinin. ## Deneme kullanıcılarını dönüştürmek ve kaybettiğim aboneleri geri kazanmak istiyorum \{#i-want-to-convert-trial-users-and-recover-churned-subscribers-via-email\} Adapty Mail, Adapty kullanıcı verilerinizi; deneme kullanıcılarını, aboneliği iptal edenleri ve diğer yaşam döngüsü olaylarını hedefleyen yapay zeka destekli e-posta kampanyalarına dönüştürür: - **Yapay zeka destekli kampanyalar**: Adapty, marka profilinizden her kampanyanın içeriğini ve tasarımını otomatik olarak oluşturur. - **Yaşam döngüsü tetikleyicileri**: Önemli yaşam döngüsü olaylarına göre kampanyaları otomatik olarak gönderin. - **Web paywall checkout**: Her alıcıya özel kişiselleştirilmiş ödeme bağlantıları — satın almalar, bunları tetikleyen e-postaya atfedilir. - **Kendi alan adınızdan gönderin**: Tüm e-postalar doğrulanmış alan adınızdan gönderilir — ayrı bir e-posta platformuna gerek yok. [Adapty Mail](adapty-mail) hakkında daha fazla bilgi edinin. ## Uygulama sürümü çıkarmadan hızlı ilerleme istiyorum \{#i-want-to-iterate-fast-without-app-releases\} Adapty entegre edildikten sonra günlük işlerin büyük çoğunluğu kontrol panelinde yapılır — yeni uygulama sürümüne gerek kalmaz: - **Flow'lar**: Görsel bir editörde paywall'lar ve onboarding'ler tasarlayın, değişiklikleri anında yayınlayın. - **Kontrol panelinden A/B testi**: Kod yazmadan denemeler başlatın, fiyatlandırmayı ayarlayın ve teklifleri değiştirin. - **Kontrol paneli analitiği**: Gelir, kayıp, deneme ve dönüşüm verilerini gerçek zamanlı olarak takip edin. - **Slack ve e-posta raporları**: Ekibiniz için önemli metriklere dair otomatik güncellemeler alın. Explore [Flows](adapty-flow-builder) veya [Analytics](charts) sayfasına göz atın. ## Web'de satış yapıyorum ve bir mobil uygulamaya ihtiyacım var \{#i-sell-on-the-web-and-need-a-mobile-app\} Kullanıcılarınız zaten bir web sitesi üzerinden ödeme yapıyorsa ve bir mobil uygulama ekliyorsanız, Adapty satın almaları platformlar arasında senkronize eder: - **Stripe ve Paddle entegrasyonu**: Web satın almalarını otomatik olarak Adapty'ye senkronize edin. - **Web'den mobil senkronizasyon**: Web'de ödeme yapan kullanıcılar uygulamanıza erişim kazanır ve tam tersi de geçerlidir. - **Birleşik çapraz platform analitiği**: Web ve mobil geliri tek bir kontrol panelinde görün. [Stripe entegrasyonu](stripe), [Paddle entegrasyonu](paddle) kurun veya [web ve mobil aboneleri nasıl senkronize edeceğinizi](sync-subscribers-from-web) öğrenin. ## Başka bir araçtan geçiş yapıyorum \{#im-migrating-from-another-tool\} Adapty, diğer abonelik platformlarından geçişi kolaylaştırır: - **Geçiş kılavuzları**: Diğer abonelik platformlarından taşınmak için adım adım talimatlar. - **Observer Mode**: Mevcut faturalama kodunuzu koruyun ve [Observer mode](observer-vs-full-mode) ile Adapty'yi aşamalı olarak benimseyin — analitik ve A/B testleriyle başlayın, hazır olduğunuzda genişletin. - **Geçmiş veri içe aktarma**: Analitiğinizin eksiksiz kalması için mevcut işlem geçmişinizi Adapty'ye aktarın. [Adapty'ye geçiş](migrate-to-adapty-from-another-solutions) ve [geçmiş verileri içe aktarma](importing-historical-data-to-adapty) hakkında bilgi edinin. --- Hâlâ keşfediyorsanız, [Hızlı Başlangıç kılavuzu](quickstart) her zaman başlamak için iyi bir yerdir. --- # File: integrate-payments --- --- title: "Mağazalar veya ödeme platformlarıyla entegre edin" description: "Adapty'yi App Store, Google Play, özel mağazalar, Stripe ve Paddle ile entegre edin." --- Adapty'ye başlamak için önce kullanıcılarınızın ürün satın aldığı mağazalarla entegre olun. Adapty, çeşitli uygulama mağazaları ve web ödeme sağlayıcılarına bağlanarak tüm uygulama içi satın alımlarınızı ve analizlerinizi tek bir yerde toplar. ## Mağazalar ve web ödemeleriyle entegrasyon \{#integrate-with-stores-and-web-payments\} Ayrıntılı entegrasyon adımları için aşağıdan mağazanızı seçin: - [App Store](initial_ios) - [Google Play](initial-android) - Web ödemeleri: - [Stripe](stripe) - [Paddle](paddle) - [Diğer mağazalar](custom-store) ## Sonraki adımlar \{#next-steps\} Mağazanızı veya ödeme platformunuzu bağladıktan sonra [ürün eklemeye](quickstart-products) geçebilirsiniz. --- # File: quickstart-products --- --- title: "Ürün ekleme" description: "Uygulama içi ürünleri veya abonelikleri Adapty'ye ekleyin ve App Store, Google Play, Stripe, Paddle veya özel mağaza listelerinizle ilişkilendirin." --- :::tip Adapty'yi programatik olarak mı kuruyorsunuz? Bu adımı [Developer CLI](developer-cli-quickstart) kullanarak tamamlayabilirsiniz. ::: Adapty'nin temel özelliklerini kullanmadan önce, sattığınız her ürünü eklemeniz ve desteklediğiniz her mağaza veya ödeme platformuyla ilişkilendirmeniz gerekir. Bu kurulum, ürünleri kullanıcıların cihazlarına sunmanıza ve bunları daha sonra analizlerde takip etmenize olanak tanır. Adapty'de uygulamanızın sattığı her şey bir **ürün**tür. Aynı öğe App Store, Google Play veya Stripe'ta mevcutsa, bunları Adapty'de tek bir ürün altında gruplandırabilirsiniz. Bir kez kurun ve tüm platformlarda tek bir yerden yönetin. Haydi ilk ürününüzü ekleyelim. <Tabs groupId="products" queryString> <TabItem value="no-products" label="Henüz mağazalarda ürün yok" default> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/qUpC2XG-r5E?si=7Komyv4_PUQ4FaEH" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> </TabItem> <TabItem value="products-in-stores" label="Mağazalarda zaten ürünler var"> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/nlkdKCF0SwY?si=VVigzHcpv3waKJmI" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> </TabItem> </Tabs> ## İlk ürününüzü ekleyin \{#add-your-first-product\} :::tip Bu hızlı başlangıç, bir ürün oluşturmak için ihtiyacınız olan temel bilgileri kapsar. Daha fazla ayrıntı için [ürün oluşturma](create-product) rehberine bakın. ::: Diyelim ki aylık bir aboneliği ürün olarak eklemek istiyorsunuz. 1. Adapty ana menüsünden [Products](https://app.adapty.io/products) bölümüne gidin. 2. Sağ üstteki **Create product** düğmesine tıklayın. <img src={require('./img/products-tab.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important **Sonraki adımlar, App Store ve/veya Google Play'de zaten ürününüz olup olmadığına bağlıdır:** ::: <Tabs groupId="products" queryString> <TabItem value="no-products" label="Henüz mağazalarda ürün yok" default> :::important Başlamadan önce [App Store](initial_ios) ve/veya [Google Play](initial-android) entegrasyonunu yapılandırdığınızdan emin olun. App Store için, Adapty'nin ürünleri iletebilmesi amacıyla [App Store Connect API anahtarını eklediğinizden](app-store-connection-configuration#step-6-add-app-store-connect-api-key) emin olun. ::: 3. **Create a new product and push to stores** seçeneğini seçin. 4. Ürün ayrıntılarını ekleyin: - **Product name**: Yalnızca Adapty kontrol panelinde size görünür olan isim. - **Access Level**: Satın alma sonrasında hangi özelliklerin açılacağını belirleyen benzersiz tanımlayıcı. Uygulamanızdaki tüm ücretli kullanıcılar aynı özelliklere erişim kazanıyorsa, varsayılan access level kullanabilirsiniz: `premium`. Daha karmaşık kurulumlar için ek [access level'lar](access-level) oluşturun. - **Subscription duration**: Listeden abonelik süresini seçin. - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: Abonelik süresi. - **Lifetime**: Uygulamanın premium özelliklerini sonsuza kadar açan ürünler için süresiz erişim periyodunu kullanın. - **Non-Subscriptions**: Abonelik olmayan ve dolayısıyla süresi bulunmayan ürünler için non-subscription kullanın. Bunlar ek özellikler, consumable ürünler vb. için açılabilir. - **Consumables**: Consumable öğeler birden fazla kez satın alınabilir. Uygulama kullanım ömrü boyunca tüketilebilirler. Örnekler arasında oyun içi para birimi ve ekstralar sayılabilir. Consumable ürünlerin access level'ları etkilemediğini lütfen göz önünde bulundurun. - **Price (USD)**: USD cinsinden ürün fiyatı. Bu fiyat, tüm ülkelerdeki fiyatları otomatik olarak hesaplamak ve ayarlamak için temel olarak kullanılacaktır. Daha sonra [farklı ülke ve bölgeler için fiyatı özelleştirebilirsiniz](edit-product#set-country-specific-prices). <img src={require('./img/create-product-push.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Save & Continue** düğmesine tıklayın ve mağaza için ürün ayrıntılarını doldurmak amacıyla **App Store** veya **Google Play** sekmesine geçin. <Tabs> <TabItem value="App Store" label="App Store" default> - **Product ID**: Ürün için kalıcı bir benzersiz kimlik oluşturun. - **Product group**: App Store Connect'te oluşturduğunuz mevcut bir ürün grubunu seçin veya **Create new Product Group** düğmesine tıklayıp adını ve kimliğini belirleyin. Adapty oluşturduktan sonra açılır listeden seçebilirsiniz. - **Screenshot**: Sunulan öğeyi veya hizmeti açıkça gösteren uygulama içi satın alma ekran görüntüsü yükleyin. Bu ekran görüntüsü yalnızca App Store incelemesi için kullanılır ve App Store'da görüntülenmez. Ekran görüntüsü boyutu ve format gereksinimlerini [buradan](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications/) inceleyebilirsiniz. :::warning Bu uygulama için ilk ürününüzse, App Store Connect'te manuel olarak incelemeye göndermeniz gerekir. Bu işlem daha sonra gerekmeyecektir. İnceleme tamamlandıktan sonra Adapty'deki ürün durumu otomatik olarak güncellenecektir. ::: </TabItem> <TabItem value="Google Play" label="Google Play" default> - **Base Product ID**: Ürün için kalıcı bir benzersiz kimlik oluşturun. - **Subscription**: Google Play Console'da oluşturduğunuz mevcut bir abonelik grubunu seçin veya **Create new Product Group** düğmesine tıklayıp adını ve kimliğini belirleyin. Adapty oluşturduktan sonra açılır listeden seçebilirsiniz. </TabItem> </Tabs> 6. iOS için, **Free duration** açılır listesinden seçim yaparak başlangıç teklifini (ücretsiz deneme) yapılandırın. Bu ilk kurulum için ücretsiz deneme başlangıç teklifi ekleyebilirsiniz. Ana ürün mağazalar tarafından onaylandıktan sonra, mağaza konsolunuzdaki mevcut kimlikleri bağlayarak [daha fazla teklif ekleyebilirsiniz](offers) (örn. promosyon, geri kazanma). :::important Başlangıç teklifleri Google Play ile otomatik olarak senkronize edilmez. App Store'un aksine, Google Play'in ayrı bir "başlangıç teklifi" türü yoktur — ücretsiz denemeler ve indirimli teklifler, bir temel planda **teklif** olarak yapılandırılır. [Teklifi Google Play Console'da oluşturun ve Adapty ürününüze bağlayın](google-play-offers). ::: </TabItem> <TabItem value="products-in-stores" label="Mağazalarda zaten ürünler var"> 3. **Connect an existing store product** seçeneğini seçin. 4. Ürün ayrıntılarını ekleyin: - **Product name**: Yalnızca Adapty kontrol panelinde size görünür olan isim. - **Access level ID**: Satın alma sonrasında hangi özelliklerin açılacağını belirleyen benzersiz tanımlayıcı. Uygulamanızdaki tüm ücretli kullanıcılar aynı özelliklere erişim kazanıyorsa, varsayılan access level kullanabilirsiniz: `premium`. Daha karmaşık kurulumlar için ek [access level'lar](access-level) oluşturun. - **Subscription duration**: Listeden abonelik süresini seçin. - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: Abonelik süresi. - **Lifetime**: Uygulamanın premium özelliklerini sonsuza kadar açan ürünler için süresiz erişim periyodunu kullanın. - **Non-Subscriptions**: Abonelik olmayan ve dolayısıyla süresi bulunmayan ürünler için non-subscription kullanın. Bunlar ek özellikler, consumable ürünler vb. için açılabilir. - **Consumables**: Consumable öğeler birden fazla kez satın alınabilir. Uygulama kullanım ömrü boyunca tüketilebilirler. Örnekler arasında oyun içi para birimi ve ekstralar sayılabilir. Consumable ürünlerin access level'ları etkilemediğini lütfen göz önünde bulundurun. - **Price (USD)**: USD cinsinden ürün fiyatı. Ürününüz zaten mağazadaysa, bu değer mağazadaki gerçek fiyatı etkilemeyecektir; listeden herhangi bir değer seçebilirsiniz. Daha sonra Adapty kontrol panelinden [farklı bölgeler için fiyatları özelleştirebilirsiniz](edit-product#set-country-specific-prices). <img src={require('./img/product-info.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <br /> 5. Mağaza ayrıntılarını ekleyin. Mağazanızı seçin: <Tabs> <TabItem value="App Store" label="App Store" default> - **App Store Product ID**: Cihazlarda ürününüze erişmek için kullanılan benzersiz tanımlayıcı. Bulamazsanız, kimliğin doğru olduğundan ve doğru uygulamaya ait olduğundan emin olun. </TabItem> <TabItem value="Google Play" label="Google Play" default> - **Google Play Product ID**: Play Store'daki ürün tanımlayıcısı. Mevcut ürün kimlikleri listesinden seçin. Bulamazsanız, kimliğin doğru olduğundan ve doğru uygulamaya ait olduğundan emin olun. - **Base plan ID**: Play Store'da ürün için temel planı tanımlayan kimlik. - **Legacy fallback product**: Yedek ürün, yalnızca eski Adapty SDK sürümlerini (2.5 ve altı) kullanan uygulamalar için kullanılır. Değeri şu biçimde belirtin: `<subscription_id>:<base_plan_id>`. :::important Başlangıç teklifleri Google Play ile otomatik olarak senkronize edilmez. App Store'un aksine, Google Play'in ayrı bir "başlangıç teklifi" türü yoktur — ücretsiz denemeler ve indirimli teklifler, bir temel planda **teklif** olarak yapılandırılır. [Teklifi Google Play Console'da oluşturun ve Adapty ürününüze bağlayın](google-play-offers). ::: <details> <summary>Google Play Ürün ve Temel Plan kimliklerini nerede bulacağınızı öğrenmek için tıklayın.</summary> 1. [Google Play Console](https://play.google.com/console/developers/android/app) hesabınızda **Monetize with Play > Products > Subscriptions** bölümüne gidin. 2. Satın alma için **Subscription** öğesini açın. 3. **Subscription details** bölümünde Ürün Kimliğini ve **Base plans and offers** bölümünün **ID and duration** sütununda Temel Plan Kimliğini göreceksiniz. <img src={require('./img/play-store-id.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Stripe" label="Stripe" default> - **Stripe Product ID**: Stripe'tan alınan benzersiz ürün tanımlayıcısı. - **Stripe Price ID**: Ürünle ilişkilendirilmiş fiyat için Stripe'tan alınan benzersiz tanımlayıcı. <details> <summary>Stripe Ürün ve Fiyat kimliklerini nerede bulacağınızı öğrenmek için tıklayın.</summary> 1. Stripe'taki [Ürün Kataloğunuza](https://dashboard.stripe.com/products?active=true) gidin. 2. İhtiyacınız olan ürünü açın. 3. Şunları göreceksiniz: - Stripe Ürün Kimliği (görünüm: `prod_...`) sağ üst köşede. - Stripe Fiyat Kimliği (görünüm: `price_...`) **Pricing** bölümünün **API ID** sütununda. <img src={require('./img/product-stripe.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Paddle" label="Paddle" default> - **Paddle Product ID**: Paddle'dan alınan benzersiz ürün tanımlayıcısı. - **Paddle Price ID**: Ürünle ilişkilendirilmiş fiyat için Paddle'dan alınan benzersiz tanımlayıcı. <details> <summary>Paddle Ürün ve Fiyat kimliklerini nerede bulacağınızı öğrenmek için tıklayın.</summary> 1. Paddle'daki [Ürün Kataloğunuza](https://vendors.paddle.com/products-v2) gidin. 2. İhtiyacınız olan ürünü açın. 3. Şunları göreceksiniz: - Paddle Ürün Kimliği (görünüm: `pro_...`) **Additional details** bölümünde. - Paddle Fiyat Kimliği (görünüm: `pri_...`) **Prices** bölümünün **ID** sütununda. <img src={require('./img/paddle-product-price.webp').default} style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Custom" label="Özel mağaza" default> Mevcut bir özel mağaza seçebilir veya yeni bir tane ekleyerek bir ürünü bununla ilişkilendirebilirsiniz. Adapty'nin yalnızca App Store, Google Play ve Stripe'tan gelen işlemleri takip ettiğini unutmayın. Özel mağazalar için, Adapty sunucu tarafı API [Set transaction yöntemi](api-adapty/operations/setTransaction) kullanarak işlemleri göndermeniz gerekecektir. </TabItem> </Tabs> 6. Gerekirse ürün için [teklif oluşturabilirsiniz](create-offer). Teklif eklemek için **Yes, add offers** düğmesine tıklayın. Aksi takdirde **No, thanks** düğmesine tıklayın. Ürününüz ürün listesinde görünecektir. <img src={require('./img/created-product.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} Ürünlerinizi Adapty'ye ekledikten sonra, satışa başlamanın tek yolu olduğu için [paywall'ları kurma](quickstart-paywalls) adımına geçebilirsiniz. --- # File: quickstart-paywalls --- --- title: "Satın almaları etkinleştir" description: "Ürünlerinizi göstermek için Adapty'de bir flow veya paywall ekleyin, ardından bunu bir placement'a bağlayın." --- :::info Bu kılavuza devam etmek için [mağaza entegrasyonunu](integrate-payments) tamamladığınızdan ve önceki [ürün ekleme kılavuzunda](quickstart-products) açıklandığı gibi en az bir ürün oluşturduğunuzdan emin olun. ::: Artık ürünleriniz hazır; şimdi bunları kullanıcılara göstermeniz gerekiyor. Adapty bunun için size üç seçenek sunar: - **Flow Builder (önerilir)**: Satın alma yolculuğunun tamamı için görsel no-code düzenleyici. Adapty SDK sonucu doğrudan native olarak render eder, bu yüzden UI kodu yazmanıza gerek yoktur. - **Manuel paywall**: Bir paywall oluşturur, ürünleri bağlar ve arayüzü uygulama kodunda kendiniz render edersiniz. - **Adapty Paywall Builder (Legacy)**: No-code paywall düzenleyicisi. Her iki seçenek de aynı şekilde tamamlanır: oluşturduğunuzu bir [placement](placements)'a bağlarsınız. Placement, uygulamanızın çalışma zamanında doğru kullanıcıya doğru içeriği getirmek için çağırdığı şeydir. <Tabs groupId="purchase-setup" queryString> <TabItem value="flow-builder" label="Flow Builder Kullan" default> :::important Flow Builder şu anda iOS, Android, React Native, Flutter ve Capacitor SDK v4 ve üzeri sürümlerini desteklemektedir. Diğer platformlar için destek yakında gelecektir. ::: Bir flow, doğrudan içine gömülmüş ürünlere sahip bir veya daha fazla ekrandan oluşur. [Flow Builder](adapty-flow-builder)'da tasarlarsınız — kod gerekmez. Adapty SDK, flow'ları her platformda yerel olarak işler. Uygulamanız `getFlow` çağrısı yapar; SDK ekranları sunar, satın almaları yönetir ve olayları raporlar. Ayrı bir UI kodu yok, yanında bakımını yapmanız gereken bir paywall yok. ## 1. Flow'u oluşturun \{#build-the-flow\} 1. Adapty ana menüsünde [**Flows**](https://app.adapty.io/flows) bölümüne gidin. 2. **Create flow**'a tıklayın ve flow'unuzu tasarlayın. [Adapty Flow Builder](adapty-flow-builder) hakkında daha fazla bilgi edinin. Aşağıdaki şablon rehberleri en yaygın senaryoları adım adım ele alır: <CustomDocCardList ids={['basic-paywall-screen', 'show-plans-bottom-sheet', 'paywall-with-tabs', 'paywall-features-per-product', 'onboarding-flow-tutorial']} /> Flow'unuz kaydedilip yayınlandıktan sonra bir placement'a bağlama adımına geçin. :::warning Flow'u yayınlamayı unutmayın! Yayınlamazsanız placement'a ekleyemezsiniz. ::: ### 2. Flow'u bir placement'a ekleyin Uygulamanızın çalışma zamanında flow'u talep edebilmesi için bir <InlineTooltip tooltip="placement">Placement, uygulamanızda bir flow, paywall, onboarding veya A/B testinin gösterildiği belirli bir noktadır. Placement'lar, içeriğinizi belirli [kitlelere](audience) yönelik hedeflemenizi sağlar. [Placement'lar](placements) hakkında daha fazla bilgi edinin.</InlineTooltip> oluşturun. En temel olanıyla başlayalım — onboarding placement'ı. Daha sonra kullanıcı yolculuğu boyunca daha fazla [anlamlı placement](choose-meaningful-placements) ekleyebilirsiniz. 1. Adapty ana menüsünde [**Placements**](https://app.adapty.io/placements) bölümüne gidin ve **Flows** sekmesine geçin. 2. **Create placement** düğmesine tıklayın. 3. Bir **Placement name** girin (örneğin `main` veya `onboarding`). Bu, Adapty Kontrol Paneli'ndeki dahili bir tanımlayıcıdır. 4. Bir **Placement ID** girin. Bu ID'yi, placement'ın flow'unu yüklemek için Adapty SDK'sında kullanacaksınız. 5. **Run flow** düğmesine tıklayın ve az önce oluşturduğunuz flow'u seçin. 6. **Save & publish** düğmesine tıklayın. Uygulama kodunuzda yalnızca placement ID'lerini sabit olarak belirtirsiniz. Geri kalan her şey — hangi flow'un çalışacağı, hangi ürünleri sattığı, nasıl görüneceği — Adapty Kontrol Paneli'nde yapılandırılır ve uygulama güncellemesi gerekmeden her an değiştirilebilir. :::tip Adapty, farklı kullanıcı gruplarına farklı flow'lar göstermenizi ve performansı analiz etmenizi sağlar. [Kitleler](audience) ve [A/B testleri](ab-tests) hakkında daha fazla bilgi edinin. ::: </TabItem> <TabItem value="manual-paywall" label="Paywallı manuel olarak uygula"> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/e4o7Z2tUGL8?si=ipwbW3VVN0fIg0R0" title="YouTube video oynatıcı" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Bir paywall, bir veya daha fazla ürün için uzaktan yapılandırılmış bir kapsayıcıdır. Adapty ürün listesini ve isteğe bağlı bir [remote config](customize-paywall-with-remote-config) JSON yükü sunar; uygulama kodunuz bunları okuyarak arayüzü oluşturur. :::tip Adapty'yi programatik olarak mı kuruyorsunuz? Bu adımı [Developer CLI](developer-cli-quickstart) kullanarak tamamlayabilirsiniz. ::: ### 1. Bir paywall oluşturun \{#1-create-a-paywall\} 1. Adapty ana menüsünden [**Paywalls**](https://app.adapty.io/paywalls) bölümüne gidin. 2. **Create paywall** düğmesine tıklayın. 3. Bir **Paywall name** girin. Bu, Adapty Kontrol Paneli'ndeki dahili bir tanımlayıcıdır. 4. **Add product** düğmesine tıklayın ve paywall'da göstermek istediğiniz ürünleri seçin. 5. (İsteğe bağlı) **Remote config** sekmesini açın ve uygulamanızın ihtiyaç duyduğu JSON verisini ekleyin (başlıklar, metinler, özellik bayrakları). Ayrıntılar için [Remote config ile paywall tasarlama](customize-paywall-with-remote-config) bölümüne bakın. 6. **Create as a draft** düğmesine tıklayın, ardından hazır olduğunuzda yayınlayın. <img src="/assets/shared/img/quickstart-paywall.gif" style={{ border: '1px solid #727272', /* kenarlık genişliği ve rengi */ width: '700px', /* resim genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalama hizalama */ }} /> Bu paywalli uygulama kodunuzda oluşturacaksınız. <InlineTooltip tooltip="paywallları manuel olarak uygulamak">Platformunuza uygun kılavuzu izleyin: [iOS](ios-implement-paywalls-manually), [Android](android-implement-paywalls-manually), [React Native](react-native-implement-paywalls-manually), [Flutter](flutter-implement-paywalls-manually), [Unity](unity-implement-paywalls-manually).</InlineTooltip> ### 2. Paywallı bir placement'a ekle \{#2-add-the-paywall-to-a-placement\} Uygulamanızın çalışma zamanında paywallı talep edebilmesi için bir <InlineTooltip tooltip="placement">Placement, uygulamanızda bir flow, paywall, onboarding veya A/B testi gösterdiğiniz belirli bir noktadır. Placement'lar, içeriğinizi belirli [kitlelere](audience) hedeflemenizi sağlar. [Placement'lar](placements) hakkında daha fazla bilgi edinin.</InlineTooltip> oluşturun. En temel olandan başlayalım — onboarding placement'ı. Daha sonra kullanıcı yolculuğu boyunca daha fazla [anlamlı placement](choose-meaningful-placements) ekleyebilirsiniz. 1. Adapty ana menüsünde [**Placements**](https://app.adapty.io/placements) bölümüne gidin ve **Paywalls** sekmesine geçin. 2. **Create placement** butonuna tıklayın. 3. Bir **Placement name** girin (ör. `main` veya `onboarding`). Bu, Adapty Kontrol Paneli'ndeki dahili bir tanımlayıcıdır. 4. Bir **Placement ID** girin. Bu kimliği, placement'ın paywallını yüklemek için Adapty SDK'sında kullanacaksınız. 5. **Run paywall** butonuna tıklayın ve az önce oluşturduğunuz paywall'ı seçin. 6. **Save & publish** butonuna tıklayın. <img src="/assets/shared/img/add-placement.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Uygulama kodunuzda yalnızca placement ID'lerini sabit olarak tanımlarsınız. Geri kalan her şey — hangi paywall'ın çalıştığı, hangi ürünleri sattığı, remote config — Adapty Kontrol Paneli'nde yapılandırılır ve uygulama güncellemesi gerektirmeden istediğiniz zaman değiştirilebilir. :::tip Adapty, farklı kullanıcı gruplarına farklı paywaller göstermenize ve performansı analiz etmenize olanak tanır. [Kitleler](audience) ve [A/B testleri](ab-tests) hakkında daha fazla bilgi edinin. ::: </TabItem> <TabItem value="paywall-builder" label="Adapty Paywall Builder (Legacy)"> [Paywall Builder](adapty-paywall-builder) ile oluşturulan bir paywall, ürünlerin doğrudan yerleştirildiği kodsuz bir ekrandır. Adapty SDK bunu yerel olarak render eder, dolayısıyla herhangi bir UI kodu yazmanız gerekmez. :::warning Paywall Builder tamamen işlevseldir, ancak Adapty artık bu araç için yeni özellik eklemiyor veya güncelleme yayınlamıyor. Yeni projeler için bunun yerine [Flow Builder](adapty-flow-builder) kullanın. ::: ### 1. Paywall'ı oluşturun \{#build-the-paywall\} 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümüne gidin. 2. **Create paywall** düğmesine tıklayın. 3. Bir **Paywall name** girin. Bu, Adapty Kontrol Paneli'ndeki dahili bir tanımlayıcıdır. 4. **Add product** düğmesine tıklayın ve paywall'da gösterilecek ürünleri seçin. 5. **Builder & Generator** sekmesini açın. Bir şablondan paywall oluşturun ya da yapay zeka ile oluşturun. 6. SDK'nın render edebilmesi için **Show on device** geçiş düğmesini açın. ### 2. Paywallı bir placement'a ekleyin \{#add-the-paywall-to-a-placement\} Uygulamanızın çalışma zamanında paywallı talep edebilmesi için bir <InlineTooltip tooltip="placement">Placement, uygulamanızda bir flow, paywall, onboarding veya A/B testi gösterdiğiniz belirli bir noktadır. Placement'lar, içeriğinizi belirli [kitlelere](audience) hedeflemenizi sağlar. [Placement'lar](placements) hakkında daha fazla bilgi edinin.</InlineTooltip> oluşturun. 1. Adapty ana menüsünde [**Placements**](https://app.adapty.io/placements) bölümüne gidin ve **Paywalls** sekmesine geçin. 2. **Create placement** düğmesine tıklayın. 3. Bir **Placement name** girin (örneğin `main` veya `onboarding`). Bu, Adapty Kontrol Paneli'ndeki dahili bir tanımlayıcıdır. 4. Bir **Placement ID** girin. Bu kimliği, placement'ın paywallini yüklemek için Adapty SDK'sında kullanacaksınız. 5. **Run paywall** düğmesine tıklayın ve oluşturduğunuz paywallı seçin. 6. **Save & publish** düğmesine tıklayın. Uygulama kodunuzda yalnızca placement ID'lerini sabit olarak yazarsınız. Geri kalan her şey — hangi paywall'ın çalıştığı, hangi ürünleri sattığı, nasıl göründüğü — Adapty Kontrol Paneli'nde yapılandırılır ve uygulama güncellemesi gerektirmeden istediğiniz zaman değiştirilebilir. </TabItem> </Tabs> ## Sonraki adımlar \{#next-steps\} Artık SDK'nın sunabileceği bir şeyiniz var. Şimdi [Adapty SDK'yı](quickstart-sdk) uygulamanıza entegre edin ve placement'ı çekmeye başlayın. --- # File: quickstart-sdk --- --- title: "Adapty SDK'yı uygulama kodunuza entegre edin" description: "Adapty'yi App Store, Google Play, özel mağazalar, Stripe ve Paddle ile entegre edin." --- Adapty SDK'yı uygulamanıza entegre ederek şunları yapabilirsiniz: - Satın alma işlemleri, makbuz doğrulama ve abonelik yönetimini hazır olarak kullanma - Uygulama güncellemesi gerektirmeden paywall oluşturma ve test etme - Sıfır kurulumla ayrıntılı satın alma analitiği alma - kohort, LTV, churn ve dönüşüm hunisi analizi dahil - Kullanıcı abonelik durumunu uygulama oturumları ve cihazlar arasında her zaman güncel tutma - Uygulamanızı yalnızca bir satır kodla pazarlama attribution ve analitik hizmetleriyle entegre etme ## Nasıl çalışır \{#how-does-it-work\} Adapty SDK'nın temel uygulaması için yalnızca üç şeye dikkat etmeniz gerekir: 1. SDK'yı yükleyin ve başlatın. 2. Uygulama içi satın alma işlemlerinin yönetimini Adapty'ye devredin. 3. profildeki abonelik durumunu izleyin. Adapty abonelik durumunu, türünü ve sona erme tarihini belirler – SDK yalnızca bu bilgiyi tüketir. Sıra ve ayrıntılar uygulamadan uygulamaya değişebilir, ancak temelde bu kadar. ## Başlarken \{#get-started\} Platformunuzu seçin ve hemen başlayın: **iOS** - **[SDK Hızlı Başlangıç](ios-sdk-overview)** - **[Örnek Uygulamalar](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)** **Android** - **[SDK Hızlı Başlangıç](android-sdk-overview)** - **[Örnek Uygulama](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)** **React Native** - **[SDK Hızlı Başlangıç](react-native-sdk-overview)** - **[Örnek Uygulamalar](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/)** **Flutter** - **[SDK Hızlı Başlangıç](flutter-sdk-overview)** - **[Örnek Uygulama](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)** **Unity** - **[SDK Hızlı Başlangıç](unity-sdk-overview)** - **[Örnek Uygulama](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)** **Capacitor** - **[SDK Hızlı Başlangıç](capacitor-sdk-overview)** - **[Örnek Uygulamalar](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples)** **Kotlin Multiplatform**: - **[SDK Hızlı Başlangıç](kmp-sdk-overview)** - **[Örnek Uygulama](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)** ## Sonraki adımlar \{#next-steps\} Adapty SDK'yı uygulama kodunda yapılandırdıktan sonra [uygulamayı test etmeye](quickstart-test) geçebilirsiniz. --- # File: quickstart-test --- --- title: "Adapty entegrasyonunuzu test edin" description: "App Store, Google Play, Stripe ve Paddle üzerinde SDK aktivasyonu, paywall getirme ve uygulama içi satın almaları test ederek Adapty entegrasyonunuzu hızlıca doğrulayın." --- Her şey hazır! Şimdi entegrasyonunuzun beklendiği gibi çalıştığından ve satın almalarınızı Adapty kontrol panelinde görebildiğinizden emin olun. Test satın alması yapmak, entegrasyonunuzun uçtan uca çalışıp çalışmadığını doğrulamanın en iyi yoludur. Uygulama içi satın almayla başlayın, ardından sonuçlarınızı doğrulayın. ## 1. Uygulama içi satın almaları test edin \{#1-test-in-app-purchases\} Mağazanıza veya ödeme platformunuza göre kılavuzu takip edin. ### App store \{#app-store\} Test hesabı (Sandbox Apple ID) kullanmanızı ve testi gerçek bir cihazda yapmanızı öneririz. Tüm test adımları hakkında daha fazla bilgi edinmek için [App Store Sandbox testi](test-purchases-in-sandbox) ile ilgili ayrıntılı makaleye gidin. :::warning En güvenilir sonuçlar için gerçek bir cihazda test edin. İsterseniz simülatörde de test yapabilirsiniz, ancak daha az güvenilir olduğu için bunu önermiyoruz. ::: ### Google Play Store \{#google-play-store\} Bir test kullanıcısı oluşturun ve uygulamanızı gerçek bir cihazda test edin. Tüm test adımları hakkında daha fazla bilgi edinmek için [Google Play Store testi](testing-on-android) ile ilgili ayrıntılı makaleye gidin. :::note Google, test için gerçek bir cihaz kullanılmasını [önermektedir](https://support.google.com/googleplay/android-developer/answer/14316361). Emülatör kullanmaya karar verirseniz, uygulamanızın düzgün çalıştığından emin olmak için emülatörde Google Play'in yüklü olduğundan emin olun. ::: ### Stripe \{#stripe\} Stripe üzerinde satın almaları test etmek için Stripe Test modu API anahtarını kullanarak Stripe'ı Adapty'ye bağlamanız gerekir. Stripe'ın Test modundan yaptığınız işlemler Adapty'de Sandbox olarak değerlendirilecektir. Tüm bağlantı adımları hakkında daha fazla bilgi edinmek için [Stripe entegrasyon makalesine](stripe#6-test-your-integration) gidin. ### Paddle \{#paddle\} Paddle üzerinde satın almaları test etmek için Paddle test ortamı API anahtarını kullanarak Paddle'ı Adapty'ye bağlamanız gerekir. Paddle'ın test ortamından yaptığınız işlemler Adapty'de Test olarak değerlendirilecektir. Tüm bağlantı adımları hakkında daha fazla bilgi edinmek için [Paddle entegrasyon makalesine](paddle#4-test-your-integration) gidin. ## 2. Test satın almalarını doğrulayın \{#2-validate-test-purchases\} Test satın alması yaptıktan sonra, Adapty Kontrol Paneli'ndeki [**Event Feed**](https://app.adapty.io/event-feed) bölümünde ilgili işlemi kontrol edin. Satın alma **Event Feed**'de görünmüyorsa, Adapty bunu takip etmiyor demektir. [Test satın almalarını doğrulama](validate-test-purchases) hakkındaki ayrıntılı kılavuzda daha fazla bilgi edinin. <img src="/assets/shared/img/test-event-feed.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Sonraki adımlar \{#next-steps\} Adapty'yi başarıyla kullanmaya başladığınız için tebrikler! Artık uygulama içi satın almalarınızı büyütmeye hazırsınız. Üretim sürümüne hazırlanın: <Button id="release-checklist"> Yayın kontrol listesi </Button> Ya da aşağıdakilerle devam edebilirsiniz: - **[A/B testi](ab-tests)**: En etkili kombinasyonları belirlemek için farklı fiyatlar, abonelik süreleri, deneme dönemleri ve görsel öğelerle deneyler yapın. - **[Analitik](how-adapty-analytics-works)**: Kullanıcı davranışını anlamak ve gelir performansını optimize etmek için ayrıntılı monetizasyon metriklerini inceleyin. - **Entegrasyonlar**: Adapty, [abonelik olaylarını](events) [Amplitude](amplitude), [AppsFlyer](appsflyer), [Adjust](adjust), [Branch](branch), [Mixpanel](mixpanel), [Facebook Ads](facebook-ads), [AppMetrica](appmetrica) ve özel [Webhook](webhook) gibi üçüncü taraf analitik ve attribution araçlarına gönderir. :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: --- # File: release-checklist --- --- title: "Yayın kontrol listesi" description: "Adapty'nin yayın kontrol listesini takip ederek uygulama güncelleme sürecinizin sorunsuz geçmesini sağlayın." --- Adapty'yi tercih ettiğiniz için çok mutluyuz! Umarız entegrasyon süreci sorunsuz geçmiştir. Bu kılavuz, uygulamanızı mağazalarda yayınlamaya hazırlamak ve monetizasyon akışının düzgün çalıştığından emin olmak için izlemeniz gereken adımları açıklar. ## Başlamadan önce gerekenler \{#pre-flight-essentials\} Doğrulamaya başlamadan önce şunlara ihtiyacınız var: - Sandbox hesabı olan gerçek bir cihaz - Adapty Kontrol Paneli'ne erişim - App Store Connect / Google Play Console'a erişim :::note Sandbox satın almaları simülatörlerde çalışabilse de ödeme diyalogları ve biyometrik doğrulama gibi tüm akışları test etmek için gerçek cihaz gereklidir. ::: <Button id="test-purchases-in-sandbox"> App Store için test kılavuzu </Button> <Button id="testing-on-android"> Google Play için test kılavuzu </Button> ## Genel doğrulamalar \{#universal-validations\} - [ ] **Mağaza bağlantısı**: Adapty'yi App Store ve/veya Google Play'e bağladığınızdan emin olun: - [ ] [App Store](initial_ios) - [ ] [Google Play](initial-android) - [ ] **Abonelik olay iletimi**: Sunucu bildirimlerinin yapılandırıldığını doğrulayın: - [ ] [App Store sunucu bildirimleri](enable-app-store-server-notifications) - [ ] [Gerçek zamanlı geliştirici bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) - [ ] **Profil tanımlama**: Kullanıcı tanımlama mantığını doğrulayın ve satın almaların doğru profile eşlendiğinden emin olun: - [ ] [Uygulama kodunuzdaki tanımlama mantığının kullanım senaryonuzla uyuştuğunu kontrol edin](ios-quickstart-identify) - [ ] [Kullanıcı profilleri arasında ücretli erişim paylaşımı için üst/mirasçı mantığını anladığınızdan emin olun](sharing-paid-access-between-user-accounts) - [ ] **Teklifler**: Uygulamanızda App Store promosyon teklifleri kullanıyorsanız, [Uygulama içi satın alma anahtarını](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) hem ana alana hem de **App Store promotional offers** bölümüne eklediğinizden emin olun. - [ ] **Veri toplama**: Gizlilik uyumluluğunu sağlayın: - [ ] GDPR veya CCPA gibi gizlilik düzenlemelerine uymak zorundaysanız ya da uygulamanız çocuklara yönelikse, [IDFA ve IP toplama ile paylaşımını etkinleştirip etkinleştirmeyeceğinizi](sdk-installation-ios#data-policies) belirleyin. - [ ] Uygulamanız AppTrackingTransparency kullanıyorsa, [yetkilendirme durumunu Adapty'ye gönderdiğinizden](ios-deal-with-att) emin olun. - [ ] **Gizlilik etiketleri**: Adapty'nin topladığı veriler ve inceleme için hangi işaretleri ayarlamanız gerektiği hakkında [daha fazla bilgi edinin](apple-app-privacy). ## Satın alma doğrulamaları \{#purchase-validations\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Yayına geçmeden önce, uygulamanızdaki satın almaların düzgün çalıştığından ve paywallınızın mağaza incelemesine hazır olduğundan emin olun. Uygulama içi satın almaları doğrulama yönteminiz, bunları nasıl uyguladığınıza bağlıdır: - Adapty Paywall Builder'da oluşturulmuş bir paywall gösteriyorsunuz - Kendi paywallınızı uyguladınız ve satın almaları yönetmek için içinde `makePurchase` metodunu kullanıyorsunuz - Adapty'yi gözlemci modunda kullanıyorsunuz (Adapty Paywall Builder veya özel paywallınızla) <Tabs groupId="paywall" queryString> <TabItem value="builder" label="Adapty Paywall Builder" default> **Hedef**: Adapty paywallı render eder, kullanıcılar ürün satın alabilir, erişim açılır ve geri yükleme akışı çalışır. - [ ] Uygulamanız, yayınlayacağınız aynı placement'tan [paywallı gösteriyor](ios-present-paywalls). - [ ] Paywall ekranda görüntüleniyor. Yükleme çok uzun sürüyorsa (örneğin, kararsız internet bağlantısı durumunda), [getirme politikanızı ayarlamayı](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) düşünün. - [ ] Paywall beklenen varyantla eşleşiyor (varsa kitle/yerel ayar). Gerekirse [kitle önceliğini değiştirebilirsiniz](change-audience-priority). - [ ] Ürünler ve fiyatlar paywall'da görünüyor. Apple'ın API'sinin test sırasında (özellikle farklı bölge yapılandırmalarında) zaman zaman yanlış fiyatlar verebileceğini unutmayın; Adapty mağaza fiyatlarını etkilemediğinden fiyat doğruluğu yerine satın alma akışı işlevselliğini test etmeye öncelik verin. - [ ] Sandbox satın alması başarıyla tamamlanıyor. Başarılı satın alma geri araması alınıyor. - [ ] Erişim açılıyor ve devam ediyor. [Ücretli erişimin mevcut Adapty profiline göre verildiğini](ios-check-subscription-status#connect-profile-with-paywall-logic) doğrulayın. - [ ] Satın alma sonrasında Adapty profilinde aktif bir access level var. - [ ] Ücretli özellikler, profil söz konusu access level'ı içerdiğinde açılıyor (yalnızca satın alma geri aramasında değil). - [ ] Satın almaları geri yükleme çalışıyor. Uygulamayı yeniden yüklediğinizde veya yeni bir cihaza kurduğunuzda, otomatik satın alma geri yükleme [Ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ayarına göre çalışıyor. Herhangi bir arka uç kimlik doğrulamanız yoksa, satın almalar ayardan bağımsız olarak otomatik olarak geri yükleniyor. Diğer durumlarda, kullanıcıların uygulamayı yeniden yükledikten sonra satın almalarını geri yükleyebildiğinden emin olun. - [ ] Mağaza inceleme gereksinimleri: - [ ] **Restore purchases** düğmesi paywall'da mevcut. Bunu paywall builder'a ekleyebilirsiniz; tıklandığında satın alma geri yüklemelerini otomatik olarak işler. - [ ] Kullanım Koşulları ve Gizlilik Politikasına paywall ekranından erişilebiliyor ve bu bağlantılara tıklandığında tarayıcıda açılıyorlar. </TabItem> <TabItem value="makepurchase" label="Özel paywall (makePurchase)" default> **Hedef**: Siz UI'yi render ediyorsunuz; Adapty satın almaları, profil güncellemelerini ve geri yüklemeleri yönetiyor. - [ ] Ürün ID'leri uygulama kodunuza sabit olarak yazılmamış. Yalnızca [placement](placements) ID'lerini sabit olarak yazıyorsunuz. - [ ] Uygulamanız, yayına alacağınız aynı placement'tan [ürünleri çekiyor](fetch-paywalls-and-products). - [ ] Ürün listesi başarıyla yükleniyor. Yükleme çok uzun sürüyorsa (örneğin siz veya kullanıcılarınız dengesiz bir internet bağlantısıyla karşılaşıyorsanız), [fetch policy ayarlarını düzenlemeyi](fetch-paywalls-and-products#fetch-paywall-information) düşünebilirsiniz. - [ ] Çekilen ürünler, beklenen varyantla eşleşiyor (varsa kitle/dil ayarlarına göre). Gerekirse [kitle önceliğini değiştirebilirsiniz](change-audience-priority). - [ ] Ürünler ve fiyatlar paywall'da görünüyor. Apple'ın API'si, test sırasında zaman zaman yanlış fiyatlar döndürebilir (özellikle farklı bölge yapılandırmalarında); bu nedenle fiyat doğruluğu yerine satın alma akışının işlevselliğini test etmeye öncelik verin; Adapty, Store fiyatlarını etkilemez. - [ ] [makePurchase](making-purchases) ile yapılan sandbox satın alması başarıyla tamamlanıyor: - [ ] Başarılı satın alma sonucu işleniyor. - [ ] Beklemedeki/başarısız/iptal edilen durumlar sorunsuz şekilde ele alınıyor. - [ ] [Remote config kullanıyorsanız](present-remote-config-paywalls), değerleri paywall'unuza doğru şekilde çekiliyor. - [ ] Bir paywall gösterildiğinde [`logShowFlow` (iOS SDK v4+) / `logShowPaywall` metodu](present-remote-config-paywalls#track-paywall-view-events) çağrılıyor. - [ ] Sandbox satın alması başarıyla tamamlanıyor. Başarılı satın alma callback'i alınıyor. - [ ] Erişim kilidi açılıyor ve devam ediyor. [Mevcut Adapty profiline göre ücretli erişimin verildiğini](ios-check-subscription-status#connect-profile-with-paywall-logic) doğrulayın. - [ ] Satın alma sonrasında Adapty profilinde aktif bir access level bulunuyor. - [ ] Profil o access level'ı içerdiğinde ücretli özellikler kilidi açılıyor (yalnızca satın alma callback'ine bağlı kalmadan). - [ ] Satın almaları geri yükleme çalışıyor. Uygulamayı yeniden yüklerken veya yeni bir cihaza yüklerken, otomatik satın alma geri yükleme işlemi [Ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ayarına göre çalışıyor. Herhangi bir backend kimlik doğrulamanız yoksa, satın almalar ayardan bağımsız olarak otomatik geri yükleniyor. Diğer durumlarda, kullanıcıların uygulamayı yeniden yükledikten sonra satın almalarını geri yükleyebildiğinden emin olun. - [ ] Store inceleme gereksinimleri: - [ ] **Restore purchases** düğmesine erişilebiliyor ve [geri yüklemeleri işliyor](restore-purchase). - [ ] Kullanım Koşulları ve Gizlilik Politikası, paywall ekranından erişilebilir durumda ve bu bağlantılara tıklandığında bir tarayıcıda açılıyorlar. </TabItem> <TabItem value="observer" label="Gözlemci modu"> **Hedef**: Satın almaları, profil güncellemelerini ve geri yüklemeleri kendiniz yönetiyorsunuz; Adapty işlem raporlamasını alıyor. - [ ] **Uygulamanız satın alma işlemlerini kendi satın alma akışınızla tamamlıyor** (StoreKit / BillingClient / backend): - [ ] Sandbox satın alma işlemi mağaza arayüzünde başarıyla tamamlanıyor. - [ ] Bekleyen/başarısız/iptal edilen durumlar uygulamanızda düzgün biçimde işleniyor. - [ ] **İşlemler Adapty'ye bildiriliyor**. - [ ] Observer modu [uygulama kodunuzda etkinleştirilmiş](implement-observer-mode). - [ ] Satın alma işlemi Adapty Event Feed'de görünüyor. - [ ] Yenilemeler, iptaller ve iadeler zamanla yansıtılıyor (geçerli olduğu durumlarda). - [ ] **Paywall görüntülemeleri izleniyor**. Bir paywall gösterildiğinde [`logShowFlow` (iOS SDK v4+) / `logShowPaywall` metodu](present-remote-config-paywalls#track-paywall-view-events) çağrılıyor. - [ ] **Satın almaları geri yükleme, uygulamanız için çalışıyor**. Uygulamayı yeniden yüklemek veya cihaz değiştirmek erişimi doğru şekilde geri yükliyor. - [ ] **Mağaza inceleme gereksinimleri**: - [ ] **Satın almaları geri yükle** eylemi erişilebilir durumda ve geri yükleme akışını tetikliyor. - [ ] Kullanım Koşulları ve Gizlilik Politikası, paywall veya satın alma ekranından erişilebilir durumda ve bir tarayıcıda açılıyor. </TabItem> </Tabs> Adapty SDK entegrasyonu hakkında sorularınız varsa, sağ alttaki yapay zeka sohbet botunu kullanabilir veya [support@adapty.io](mailto:support@adapty.io) adresinden bize ulaşabilirsiniz. --- # File: observer-vs-full-mode --- --- title: "Observer mode" description: "Abonelikler için Adapty'de Observer Mode ve Full Mode'u karşılaştırın." --- Adapty, gelirlerinizi ve abone tabanınızı artırmak için tasarlanmış güçlü ve esnek bir uygulama içi satın alma platformudur. Belirli kullanıcı segmentlerine göre özelleştirilebilen paywall'lar, fiyatlandırma, süre, deneme dönemleri ve görsel öğeler için A/B testi, uygulama gelir analizine yönelik kapsamlı analitik araçlar ve üçüncü taraf entegrasyonlar gibi özellikleriyle Adapty, büyüme stratejinizi destekler. Ancak mevcut bir satın alma altyapınız varsa ve Adapty'nin sistemine geçmeye hazır değilseniz, Adapty Observer mode'u inceleyebilirsiniz. Bu sınırlı mod; Adapty paywall'larının kullanımını, bunların kullanıcı kitlesine göre hedeflenmesini, yenileme ve ödeme yeniden denemeleri dahil aboneliklerin yönetimini dışarıda bırakır ve yalnızca analitiğe odaklanır. Sınırlamalarına rağmen Observer mode, attribution sistemleriyle entegrasyon, gelişmiş analitik, mesajlaşma ve CRM profilleri dahil güçlü analitik yetenekler sunar. Her iki mod da aynı fiyata sunulmakta ve mobil uygulamanızın güncellenmesini gerektirmektedir. Dolayısıyla tercih, temelde tam işlevsellik için Adapty altyapısına geçiş yapmak ya da mevcut altyapınızı koruyarak yalnızca üçüncü taraf entegrasyonlar ve analitik yeteneklerden yararlanmak arasında olmaktadır. | İşlevsellik | Observer mode | Full mode | |-------------|-------------|---------| | **Kapsamlı Analitik** | ✅ | ✅ | | **Üçüncü Taraf Entegrasyonlar** | ✅ | ✅ | | **Satın alma olaylarına yanıt vererek kullanıcılara ücretli erişim verme/kısıtlama** | ❌ | ✅ | | **Satın Alma Altyapısını Yöneten** | Siz | Adapty | | **A/B Testi** | <p>Mümkündür, ancak Full Mode'a kıyasla önemli miktarda ek kodlama ve yapılandırma gerektirir.</p> | ✅ | | **Uygulama Süresi** | <p>Analitik ve entegrasyonlar için: Bir saatten az</p><p>A/B testleriyle birlikte: Kapsamlı testlerle birlikte bir haftaya kadar</p> | Birkaç saat | ## Observer Mode nasıl çalışır \{#how-observer-mode-works\} Observer mode'da Apple/Google'dan gelen yeni işlemleri Adapty SDK'ya bildirirsiniz ve Adapty SDK bunları Adapty backend'e iletir. Uygulamanızdaki ücretli içeriğe erişimi yönetmek, işlemleri tamamlamak, yenilemeleri yönetmek, ödeme sorunlarını çözmek ve benzeri konular sizin sorumluluğunuzdadır. ## Observer mode nasıl kurulur \{#how-to-set-up-observer-mode\} 1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu kurun. 2. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak bu modu etkinleştirin. [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk), [Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform#activate-adapty-sdk) ve [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk) için kurulum talimatlarını takip edin. 3. iOS ve iOS tabanlı çapraz platform framework'ler için mevcut satın alma altyapınızdaki işlemleri Adapty'ye [bildirin](report-transactions-observer-mode). 4. (isteğe bağlı) Üçüncü taraf entegrasyonları kullanmak istiyorsanız bunları [Üçüncü taraf entegrasyonunu yapılandırma](configuration) konusunda açıklandığı şekilde ayarlayın. :::warning Observer mode'da çalışırken Adapty SDK işlemleri sonlandırmaz, bu nedenle bu konuyu kendiniz yönettiğinizden emin olun. ::: ## Observer mode'da paywall ve A/B testleri nasıl kullanılır \{#how-to-use-paywalls-and-ab-tests-in-observer-mode\} Observer mode'da Adapty SDK, satın almaları kendi altyapınızda gerçekleştirdiğiniz için satın almaların kaynağını belirleyemez. Bu nedenle Observer mode'da paywall ve/veya A/B testi kullanmak istiyorsanız, işlem bildirirken uygulama mağazasından gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Bunlara ek olarak, Paywall Builder ile tasarlanan paywall'ların Observer mode kullanılırken özel bir şekilde görüntülenmesi gerekir: - Observer mode'da paywall'ları [iOS](implement-observer-mode) veya [Android](android-present-paywall-builder-paywalls-in-observer-mode) için görüntüleyin. - Observer mode'da işlem bildirirken [satın alma işlemlerini paywall'larla ilişkilendirin](report-transactions-observer-mode). --- # File: migration-from-revenuecat --- --- title: "RevenueCat'ten Geçiş" description: "Adım adım rehberimizle RevenueCat'ten Adapty'ye geçiş yapın." --- Geçiş planınız 5 mantıksal adımdan oluşur ve ortalama 2 saat sürer. Geçişlerin %90'ı bir iş gününden kısa sürer. 1. Temel farklılıkları öğrenin; Adapty hesabı oluşturun ve hazırlayın _(5 dakika)_; 2. RevenueCat SDK yerine platformunuz için Adapty SDK'yı yükleyin ([iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity)) _(1 saat)_; 3. Adapty'ye [Apple App Store sunucu bildirimleri](enable-app-store-server-notifications) kurun ve isteğe bağlı olarak [ham olay iletmeyi](enable-app-store-server-notifications#raw-events-forwarding) etkinleştirin _(5 dakika)_; 4. Uygulamanızın güncellemelerini test edin ve yayınlayın _(30 dakika)_; 5. (İsteğe bağlı) RevenueCat desteğinden geçmiş verileri CSV formatında isteyin _(5 dakika)_; 6. (İsteğe bağlı) Adapty desteği aracılığıyla geçmiş verileri içe aktarın _(30 dakika)_. :::info Aboneleriniz otomatik olarak geçiş yapar Daha önce abonelik etkinleştirmiş tüm kullanıcılar, Adapty SDK içeren uygulamanın yeni sürümünü açar açmaz otomatik olarak Adapty'ye taşınır. Abonelik durumu doğrulaması ve premium erişim otomatik olarak geri yüklenir. ::: Adapty SDK içeren uygulamanızın yeni sürümünü yayınlamadan önce [yayın kontrol listemizi](release-checklist) gözden geçirdiğinizden emin olun. ## Temel farklılıkları öğrenin; Adapty hesabı oluşturun ve hazırlayın \{#learn-the-core-differences-create-and-prepare-an-adapty-account\} Adapty ve RevenueCat SDK'ları benzer şekilde tasarlanmıştır. En büyük fark ağ kullanımı ve hızdır: Adapty SDK, talep ettiğinizde bilgileri olabildiğince hızlı sunmak için tasarlanmıştır. Örneğin bir paywall talep ettiğinizde, onboarding veya paywallınızı önceden oluşturmak için önce [remote config](customize-paywall-with-remote-config) gelir, ardından ürünler ayrı bir istekle alınır. İsimlendirme biraz farklıdır: | RevenueCat | Adapty | | :---------- | :-------------- | | Package | Product | | Offering | Paywall | | Paywall | Paywall Builder | | Entitlement | Access level | Adapty'de [placement](placements) kavramı vardır. Placement, uygulamanızda kullanıcının satın alma yapabileceği mantıksal bir yerdir. Çoğu durumda bir ya da iki placement'ınız olur: - Onboarding (tüm satın almaların %80'i burada gerçekleşir); - Genel (onboarding sonrası ayarlarda veya uygulama içinde gösterilen). <img src="/assets/shared/img/2406d97-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adapty SDK'yı yükleyin ve RevenueCat SDK'yı değiştirin \{#install-adapty-sdk-and-replace-revenuecat-sdk\} Uygulamanıza platformunuz için Adapty SDK'yı yükleyin ([iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity)). Uygulama tarafında birkaç SDK metodunu değiştirmeniz gerekecek. En yaygın fonksiyonlara ve bunları Adapty SDK metodlarıyla nasıl değiştireceğinize bakalım. ### SDK aktivasyonu \{#sdk-activation\} `Purchases.configure` yerine `Adapty.activate` kullanın. ### Paywall alma (offering'ler) \{#getting-paywalls-offerings\} `Purchases.shared.getOfferings` yerine [`Adapty.getPaywall`](fetch-paywalls-and-products#fetch-paywall-information) kullanın. Adapty'de paywallı her zaman [placement id](placements) üzerinden talep edersiniz. Pratikte en fazla 1-2 paywall çektiğinizden, bu yapıyı SDK'yı hızlandırmak ve ağ kullanımını azaltmak amacıyla bilerek böyle tasarladık. ### Kullanıcı (müşteri profili) alma \{#getting-a-user-customer-profile\} `Purchases.shared.getCustomerInfo` yerine `Adapty.getProfile` kullanın. ### Ürün alma \{#getting-products\} RevenueCat'te şu yapıyı kullanırsınız: `Purchases.shared.getOfferings` ve ardından `self.offering?.availablePackages`. Adapty'de önce bir paywall talep edersiniz (yukarıya bakın) — bu sayede Adapty'nin [remote config](customize-paywall-with-remote-config)'una anında erişirsiniz — ardından [`Adapty.getPaywallProducts`](fetch-paywalls-and-products#fetch-products) ile ürünleri alırsınız. ### Satın alma yapma \{#making-a-purchase\} `Purchases.shared.purchase` yerine [`Adapty.makePurchase`](making-purchases#make-purchase) kullanın. ### Access level (entitlement) kontrolü \{#checking-access-level-entitlement\} Müşteri profilini alın (önce yukarıyı okuyun) ve ardından şunu değiştirin: `customerInfo?.entitlements["premium"]?.isActive == true` şununla: [`profile.accessLevels["premium"]?.isActive == true`](subscription-status#retrieving-the-access-level-from-the-server). ### Satın alma geri yükleme \{#restore-purchase\} `Purchases.shared.restorePurchases` yerine [`Adapty.restorePurchases`](restore-purchase) kullanın. ### Kullanıcının giriş yapıp yapmadığını kontrol etme \{#check-if-the-user-is-logged-in\} `Purchases.shared.isAnonymous` yerine `if profile.customerUserId == nil` kullanın. ### Kullanıcı girişi \{#log-in-user\} `Purchases.shared.logIn` yerine [`Adapty.identify`](identifying-users#set-customer-user-id-after-configuration) kullanın. ### Kullanıcı çıkışı \{#log-out-user\} `Purchases.shared.logOut` yerine [`Adapty.logout`](identifying-users#logging-out-and-logging-in) kullanın. ## App Store sunucu tarafı bildirimlerini Adapty'ye geçirin \{#switch-app-store-server-side-notifications-to-adapty\} Bunu nasıl yapacağınızı [buradan](migrate-to-adapty-from-another-solutions#changing-apple-server-notifications) okuyun. ## Uygulamanızın yeni sürümünü test edin ve yayınlayın \{#test-and-release-a-new-version-of-your-app\} Buradasanız şunları yapmışsınızdır: - [x] Adapty Kontrol Panelini yapılandırdınız - [x] Adapty SDK'yı yüklediniz - [x] SDK mantığını Adapty fonksiyonlarıyla değiştirdiniz - [x] App Store sunucu tarafı bildirimlerini Adapty'ye geçirdiniz ve isteğe bağlı olarak RevenueCat'e ham olay iletmeyi etkinleştirdiniz - [ ] Sandbox satın alması yaptınız - [ ] Yeni bir uygulama sürümü yayınladınız Yukarıdaki maddeleri işaretlediyseniz, Sandbox'ta bir test satın alması yapın ve uygulamayı yayınlayın. :::info [Yayın kontrol listesini](release-checklist) gözden geçirin. Mevcut entegrasyonu doğrulamak ya da [attribution](attribution-integration) veya [analitik](analytics-integration) entegrasyonları gibi ek özellikler eklemek için listemizi kullanarak son kontrolü yapın. ::: ## (İsteğe bağlı) RevenueCat geçmiş verilerinizi CSV formatında dışa aktarın \{#optional-export-your-revenuecat-historical-data-in-csv-format\} :::warning Geçmiş veri aktarımını aceleye getirmeyin SDK içeren sürümü yayınladıktan sonra en az bir hafta beklemeniz gerekir. Bu süre zarfında SDK üzerinden satın alma fiyatlarına ilişkin tüm bilgileri alırız; böylece içe aktardığınız veriler çok daha doğru olur. ::: RevenueCat'ten geçmiş verilerinizi CSV formatında [RevenueCat'in resmi belgelerindeki](https://www.revenuecat.com/docs/integrations/scheduled-data-exports) talimatları izleyerek dışa aktarın. ## (İsteğe bağlı) RevenueCat desteğinden Google Purchase Token'larını isteyin \{#optional-ask-revenuecat-support-for-google-purchase-tokens\} Google Play işlemlerini içe aktarmanız gerekiyorsa, [destek sayfaları](https://app.revenuecat.com/settings/support) üzerinden RevenueCat desteğiyle iletişime geçerek Google Purchase Token'larını içeren bir CSV dosyası talep edin. Google Purchase Token, Google Play'in her işlem için sağladığı benzersiz bir tanımlayıcıdır ve Adapty'de satın almaların doğru şekilde takip edilip doğrulanması için gereklidir. Bu bilgi standart dışa aktarma dosyasına dahil değildir. Dosya şu üç sütunu içerir: - `user_id` - `google_purchase_token` - `google_product_id` ## Geçmiş verilerinizi aktarmak için bize yazın \{#write-us-to-import-your-historical-data\} Web sitesi mesajlaşma aracı üzerinden veya CSV dosyalarınızla birlikte [support@adapty.io](mailto:support@adapty.io) adresine e-posta göndererek bizimle iletişime geçin. 1. RevenueCat'ten dışa aktardığınız CSV dosyasını doğrudan destek ekibimize gönderin. 2. Google Play işlemlerini içe aktarıyorsanız, RevenueCat desteğinden aldığınız Google Purchase Token'larını içeren CSV dosyasını da ekleyin. 3. Customer User ID olarak (Adapty'nin birincil kullanıcı tanımlayıcısı) hangi kullanıcı ID'sinin kullanılması gerektiğini belirtin: `rc_original_app_user_id` mi yoksa `rc_last_seen_app_user_id_alias` mi. Destek Ekibimiz işlemlerinizi Adapty'ye aktaracaktır. Her işlem için aşağıdaki veriler Adapty'ye aktarılır: | Parametre | Açıklama | | ----------------------------- | ------------------------------------------------------------ | | user_id | Customer User ID, Adapty'deki ve sisteminizde kullanıcınızın ana tanımlayıcısı. | | apple_original_transaction_id | Abonelik zincirleri için bu, `store_original_transaction_id` ile bağlantılı orijinal işlemin satın alma tarihidir. | | google_product_id | Google Play Store'daki ürün ID'si. | | google_purchase_token | Google Play'in her işlem için sağladığı, doğrulama için gerekli benzersiz tanımlayıcı. | | country | Kullanıcının ülkesi. | | created_at | Kullanıcının oluşturulma tarihi ve saati. | | subscription_expiration_date | Aboneliğin sona erme tarihi ve saati. | | email | Son kullanıcının e-posta adresi. | | phone_number | Son kullanıcının telefon numarası. | | idfa | Apple'ın bir kullanıcının cihazına atadığı Reklamverenler için Tanımlayıcı (IDFA). | | idfv | Bir geliştirici tarafından tüm uygulamalara atanan ve o uygulamalar arasında cihazda paylaşılan Satıcılar için Tanımlayıcı (IDFV). | | advertising_id | Reklamcıların takip amacıyla kullanabileceği, Android işletim sistemi tarafından sağlanan benzersiz tanımlayıcı. | | attribution_channel | Pazarlama kanalı adı. | | attribution_campaign | Pazarlama kampanyası adı. | | attribution_ad_group | Attribution reklam grubu. | | attribution_ad_set | Attribution reklam seti. | | attribution_creative | Attribution kreatif anahtar kelimesi. | Bunlara ek olarak, şu entegrasyonlara ait entegrasyon tanımlayıcıları da içe aktarılacaktır: Amplitude, Mixpanel, AppsFlyer, Adjust ve FacebookAds. ## SSS \{#faq\} ### Adapty SDK'yı başarıyla yükledim ve yeni bir uygulama sürümü yayınladım. Adapty SDK'lı sürüme geçmeyen eski abonelerime ne olacak? \{#i-successfully-installed-adapty-sdk-and-released-a-new-app-version-with-it-what-will-happen-to-my-legacy-subscribers-who-did-not-update-to-a-version-with-adapty-sdk\} Kullanıcıların büyük çoğunluğu telefonlarını geceleri şarj eder; App Store da genellikle tüm uygulamaları bu sırada otomatik olarak günceller, dolayısıyla bu bir sorun olmamalıdır. Güncelleme yapmayan küçük bir ücretli abone grubu olabilir, ancak bu kullanıcılar premium içeriğe erişmeye devam eder. Onları güncellemeye zorlamanıza gerek yok. ### RevenueCat'teki geçmiş verilerimi mümkün olduğunca hızlı dışa aktarmam mı gerekiyor, yoksa kaybeder miyim? \{#do-i-need-to-export-my-historical-data-from-revenuecat-as-quickly-as-possible-or-will-i-lose-it\} Çok acele etmenize gerek yok; önce Adapty SDK ile bir sürüm yayınlayın, ardından geçmiş verilerinizi bize iletin. Kullanıcılarınızın ödeme geçmişini geri yükleyip [profiller](profiles-crm) ve [grafikler](charts) bölümlerini dolduracağız. ### MMP (AppsFlyer, Adjust vb.) ve analitik (Mixpanel, Amplitude vb.) kullanıyorum. Her şeyin düzgün çalışacağından nasıl emin olabilirim? \{#i-use-mmp-appsflyer-adjust-etc-and-analytics-mixpanel-amplitude-etc-how-do-i-make-sure-that-everything-will-work\} Öncelikle SDK'mız aracılığıyla veri göndermek istediğiniz üçüncü taraf hizmetlerinin ID'lerini bize iletmeniz gerekir. [Attribution entegrasyonu](attribution-integration) ve [analitik entegrasyonu](analytics-integration) kılavuzlarını okuyun. Geçmiş veriler ve eski kullanıcılar için **RevenueCat'ten dışa aktardığınız verilerdeki bu ID'leri bize aktardığınızdan emin olun.** --- # File: migration-from-superwall --- --- title: "Superwall'dan Geçiş" description: "Her SDK çağrısını ve kavramı eşleştiren adım adım kılavuzla Superwall'dan Adapty'ye geçin." --- Superwall'dan Adapty'ye geçişlerin büyük çoğunluğu yaklaşık iki saat sürer. SDK'yı değiştirirsiniz, mağaza sunucu bildirimlerinizi Adapty'ye yönlendirirsiniz ve yeni bir uygulama sürümü yayınlarsınız. Ücretli aboneleriniz erişimlerini korur — Adapty, ilk açılışta bunu App Store ve Google Play makbuzlarından otomatik olarak geri yükler. :::info Aboneleriniz otomatik olarak geçiş yapacak Bir aboneliği etkinleştirmiş olan tüm kullanıcılar, Adapty SDK'sı ile yeni bir uygulama sürümünü açtıklarında Adapty'ye geçer. Abonelik durumu doğrulama ve premium erişim otomatik olarak geri yüklenir. ::: ## Bu kılavuz nasıl düzenlenmiştir \{#how-this-guide-is-organized\} Geçiş altı adımdan oluşur: 1. [Superwall kavramlarını Adapty'ye eşleştirin](#map-your-superwall-concepts-to-adapty) 2. [Adapty SDK'sını yükleyin](#install-the-adapty-sdk) 3. [SDK çağrılarını değiştirin](#replace-sdk-calls) 4. [App Store ve Google Play sunucu bildirimlerini değiştirin](#switch-app-store-and-google-play-server-notifications) 5. [Test edin ve yayınlayın](#test-and-release) 6. [(İsteğe bağlı) Geçmiş verileri içe aktarın](#optional-import-historical-data) ## Superwall kavramlarını Adapty'ye eşleştirin \{#map-your-superwall-concepts-to-adapty\} Superwall kavramlarının büyük çoğunluğunun Adapty'de doğrudan bir karşılığı vardır: | Superwall | Adapty | Ne değişiyor | | :------------------- | :------------------------------------------------ | :--------------------------------------------------------------------------- | | Campaign | [Placement](placements) + [Audience](audience) | Kampanya mantığı, bir placement (konum) ve bir kitle (kural) olarak ikiye ayrılır. | | Placement | [Placement](placements) | Aynı kavram, aynı isim. | | Audience filter | [Audience](audience) | Kural kümeleri bir placement içinde bulunur. | | Entitlement | [Access level](access-level) | Adlandırılmış tanımlayıcı (örneğin, `premium`). | | WebView paywall | [Paywall Builder paywall](adapty-paywall-builder) | Adapty SDK tarafından `WKWebView` yerine native olarak render edilir. | | `PurchaseController` | Yerleşik | Uygulanacak protokol yok — satın almaları Adapty yönetir. | | Feature gating | [Access level](access-level) kontrolü | `profile.accessLevels["premium"]?.isActive` değerini kontrol edin. | Koda dokunmadan önce dikkat edilmesi gereken iki zihinsel değişim var: - **Getirme ve gösterme ayrı adımlardır**: Superwall'un `register` fonksiyonu, paywallı getirir, kampanyayı değerlendirir ve UI'ı tek bir çağrıda sunar. Adapty bu adımları ayırır — paywallı getirirsiniz, yapılandırmasını alırsınız ve ardından gösterirsiniz. Bu değişiklik birkaç satır ekler ama yapılandırmaları önceden yüklemenize, özel bir yükleme durumu göstermenize veya kendi mantığınıza göre gösterimi iptal etmenize olanak tanır. - **Abonelik durumu access level başınadır**: Superwall, tek bir yayımlanan `subscriptionStatus` özelliği sunar. Adapty, adlandırılmış access level'larla bir [`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile) döndürür; böylece bir kullanıcı `sports` ve `science` access level'larını bağımsız olarak tutabilir. Eş zamanlı okumalar için, her görünüm yüklemesinde `getProfile()` çağırmak yerine profili `AdaptyDelegate`'ten önbelleğe alın. ## Adapty SDK'sını yükleyin \{#install-the-adapty-sdk\} Platformunuz için Adapty SDK'sını yükleyin — [iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity) veya [Capacitor](sdk-installation-capacitor) — ve aynı anda projenizden SuperwallKit'i kaldırın. ## SDK çağrılarını değiştirin \{#replace-sdk-calls\} Entegrasyonunuzun her alanını inceleyin ve Superwall çağrısını Adapty karşılığıyla değiştirin. Her alt bölümün sonundaki bağlantılar yedi platform SDK'sının tamamını kapsar — uygulamanızla eşleşen platformu takip edin. ### SDK'yı başlatın \{#initialize-the-sdk\} `Superwall.configure` yerine `Adapty.activate` kullanın. Platformunuz için kurulum kılavuzuna bakın — [iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity) veya [Capacitor](sdk-installation-capacitor). ### Kullanıcıları tanımlayın ve oturumu kapatın \{#identify-and-log-out-users\} `Superwall.shared.identify` yerine `Adapty.identify`, `Superwall.shared.reset` yerine `Adapty.logout` kullanın. Her iki SDK de ilk açılışta anonim bir profil oluşturur, bu nedenle bu çağrılar yalnızca kullanıcı oturum açtığında veya kapattığında gereklidir. Tanımladıktan sonra paywallları yeniden getirin — yeni kullanıcı farklı bir kitleye çözümlenebilir. Platformunuz için tanımlama kılavuzuna bakın — [iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Kotlin Multiplatform](kmp-identifying-users), [Unity](unity-identifying-users) veya [Capacitor](capacitor-identifying-users). ### Paywall getirin ve gösterin \{#fetch-and-present-a-paywall\} `Superwall.shared.register` yerine iki adımlı bir flow kullanın: `Adapty.getPaywall` ile paywallı getirin, `AdaptyUI.getPaywallConfiguration` ile görünüm yapılandırmasını yükleyin ve ardından gösterin. Dikkat edilmesi gereken iki fark: - **Feature gating, `feature:` kapanışının yerini alır**: Paywall kapandıktan sonra, dönen profildeki (veya `Adapty.getProfile` üzerindeki) aktif access level'ı kontrol edin ve oradan devam edin. - **Paywalllar SDK tarafından render edilir**: Superwall, paywallları bir `WKWebView` içinde render eder. Adapty, Paywall Builder paywalllarını native olarak render eder — fontlar, ürün bilgileri ve düğmeler SDK tarafından çizilir. Platformunuz için paywall hızlı başlangıç kılavuzuna bakın — [iOS](ios-quickstart-paywalls), [Android](android-quickstart-paywalls), [React Native](react-native-quickstart-paywalls), [Flutter](flutter-quickstart-paywalls), [Kotlin Multiplatform](kmp-quickstart-paywalls), [Unity](unity-quickstart-paywalls) veya [Capacitor](capacitor-quickstart-paywalls). ### Abonelik durumunu kontrol edin \{#check-subscription-status\} `Superwall.shared.subscriptionStatus` yerine profilin adlandırılmış access level'ında şu kontrolü yapın: `profile.accessLevels["premium"]?.isActive`. `@Published` özellik deseni yerine `AdaptyDelegate.didLoadLatestProfile(_:)` aracılığıyla değişiklikleri izleyin ve eş zamanlı okumalar için profili kendi tarafınızda önbelleğe alın. Platformunuz için abonelik durumu kılavuzuna bakın — [iOS](ios-check-subscription-status), [Android](android-check-subscription-status), [React Native](react-native-check-subscription-status), [Flutter](flutter-check-subscription-status), [Kotlin Multiplatform](kmp-check-subscription-status), [Unity](unity-check-subscription-status) veya [Capacitor](capacitor-check-subscription-status). ### Satın almaları ve geri yüklemeleri yönetin \{#handle-purchases-and-restores\} Paywall Builder ile her iki SDK de satın almaları paywall UI'ı içinde otomatik olarak işler — **bu adımı atlayabilirsiniz**. Özel paywalllar için Superwall bir `PurchaseController` uygulaması gerektirir. Adapty gerektirmez: `PurchaseController.purchase` yerine `Adapty.makePurchase`, `PurchaseController.restorePurchases` yerine `Adapty.restorePurchases` kullanın. SDK, doğrulamayı kendi başına yönetir. Platformunuz için özel paywall hızlı başlangıç kılavuzuna bakın — [iOS](ios-quickstart-manual), [Android](android-quickstart-manual), [React Native](react-native-quickstart-manual), [Flutter](flutter-quickstart-manual), [Kotlin Multiplatform](kmp-quickstart-manual), [Unity](unity-quickstart-manual) veya [Capacitor](capacitor-quickstart-manual). ### Kullanıcı özelliklerini ayarlayın \{#set-user-attributes\} `Superwall.shared.setUserAttributes` yerine `Adapty.updateProfile` kullanın. Platformunuz için kullanıcı özellikleri kılavuzuna bakın — [iOS](setting-user-attributes), [Android](android-setting-user-attributes), [React Native](react-native-setting-user-attributes), [Flutter](flutter-setting-user-attributes), [Kotlin Multiplatform](kmp-setting-user-attributes), [Unity](unity-setting-user-attributes) veya [Capacitor](capacitor-setting-user-attributes). ## App Store ve Google Play sunucu bildirimlerini değiştirin \{#switch-app-store-and-google-play-server-notifications\} Mağaza sunucu bildirimlerinizi Adapty'ye yönlendirin. Adapty bunlar olmadan da çalışır; ancak analitik, üçüncü taraf entegrasyonlar ve A/B testi metrikleri bunlara bağlıdır: - **App Store**: [App Store sunucu bildirimlerini etkinleştirin](enable-app-store-server-notifications) kılavuzunu takip edin. - **Google Play**: [Gerçek zamanlı geliştirici bildirimlerini etkinleştirin](enable-real-time-developer-notifications-rtdn) kılavuzunu takip edin. Yayın sürecinde Superwall ve Adapty'yi paralel çalıştırmak istiyorsanız [raw events forwarding](enable-app-store-server-notifications#raw-events-forwarding) özelliğini kullanın — Adapty, yeni entegrasyonu doğrularken mağaza olaylarını Superwall'a proxy'ler. ## Test edin ve yayınlayın \{#test-and-release\} Yayınlamadan önce her maddeyi işaretleyin: - [x] Adapty Kontrol Paneli yapılandırıldı (ürünler, paywalllar, placement'lar, access level'lar) - [x] Adapty SDK'sı yüklendi - [x] Superwall SDK çağrıları Adapty karşılıklarıyla değiştirildi - [x] App Store ve Google Play sunucu bildirimleri Adapty'ye yönlendirildi - [ ] Sandbox satın alması yapıldı - [ ] Yeni uygulama sürümü gönderildi Son bir doğrulama geçişi için [yayın kontrol listesine](release-checklist) bakın. ## (İsteğe bağlı) Geçmiş verileri içe aktarın \{#optional-import-historical-data\} Superwall, abonelik durumunuza sahip değildir — App Store ve Google Play sahiptir. Adapty, ilk açılışta makbuzları doğrular, bu nedenle ücretli kullanıcılar herhangi bir içe aktarma olmadan erişimlerini korur. Adapty analitiğine geçmiş işlemlerin yedeklenmesini istiyorsanız [Adapty'ye geçmiş verileri içe aktarın](importing-historical-data-to-adapty) kılavuzunu takip edin. SDK'nın güncel satın alma fiyatlarını toplaması için zaman tanımak amacıyla SDK sürümünden en az bir hafta sonra bekleyin. ## SSS \{#faq\} ### Uygulamayı güncellemeyen abonelere ne olur? \{#what-happens-to-subscribers-who-dont-update-the-app\} Kullanıcıların büyük çoğunluğu uygulamalarını gece otomatik olarak günceller, bu nedenle eski sürümdeki kullanıcı payı hızla azalır. Eski sürümdeki aboneler erişimlerini doğrudan App Store veya Google Play aracılığıyla korur — güncellemeyi zorunlu kılmanıza gerek yoktur. ### Superwall kampanya kitleleri aktarılıyor mu? \{#do-my-superwall-campaign-audiences-carry-over\} Hayır. Superwall kitle filtreleri ve Adapty kitleleri farklı kontrol panellerinde yapılandırılır ve farklı tanımlayıcılar kullanır. Hedeflemenizi Adapty [placement'ları](placements) içinde [kitle](audience) olarak yeniden oluşturun. Çoğu uygulama bir veya iki placement çalıştırır (onboarding ve genel uygulama içi tetikleyici), bu nedenle yeniden yapılandırma genellikle kısa sürer. ### Adapty'nin `getPresentationResult` karşılığı var mı? \{#does-adapty-have-an-equivalent-to-getpresentationresult\} Tek bir çağrı olarak mevcut değil. Bir placement'ın paywall gösterip göstermeyeceğini kontrol etmek için `Adapty.getPaywall(placementId:)` çağırın ve sonuca göre yönlendirin. Çağrı başarılı olursa, o kullanıcının kitlesi için bir paywall atanmış demektir. Hiçbir paywall yapılandırılmadığı için başarısız olursa, gösterimi atlayın ve yedek mantığınızı çalıştırın. --- # File: importing-historical-data-to-adapty --- --- title: "Geçmiş verileri Adapty'ye aktarma" description: "Ayrıntılı analizler için geçmiş verileri Adapty'ye aktarın." --- Adapty SDK'yı yükleyip uygulamanızı yayınladıktan sonra, kullanıcılarınıza ve abonelerinize [Profiller](profiles-crm) bölümünden erişebilirsiniz. Peki ya eski bir altyapınız varsa ve Adapty'ye geçiş yapmanız gerekiyorsa ya da mevcut verilerinizi Adapty'de görmek istiyorsanız? :::note Veri aktarımı zorunlu değildir Adapty SDK entegre edilmiş uygulamayı açtıklarında Adapty, geçmiş kullanıcılara otomatik olarak access level tanıyacak ve satın alma olaylarını geri yükleyecektir. Bu kullanım senaryosunda geçmiş veri aktarımı gerekli değildir. Ancak önemli miktarda geçmiş işleminiz varsa veri aktarımı, analizlerinizin daha doğru olmasını sağlar; yine de genel olarak geçiş için zorunlu değildir. ::: Verileri Adapty'ye aktarmak için: 1. İşlemlerinizi bir CSV dosyasına aktarın (iOS, Android ve Stripe için ayrı dosyalar hazırlanmalıdır). Ayrıntılı gereksinimler için aşağıdaki [İçe aktarma dosyası formatı bölümüne](importing-historical-data-to-adapty#import-file-format) bakın. 2. Herhangi bir dosya 1 GB'ı aşıyorsa, yaklaşık 100 satırlık bir veri örneği hazırlayın. 3. Tüm dosyaları Google Drive'a yükleyin (sıkıştırabilirsiniz, ancak ayrı tutun). 4. iOS işlemleri için, StoreKit 1 kullansanız bile [**App settings**](https://app.adapty.io/settings/ios-sdk) içindeki **In-app purchase API** bölümünün **Issuer ID**, **Key ID** ve **Private key** (.P8 dosyası) ile doldurulduğundan emin olun. Ayrıntılı talimatlar için [Issuer ID ve Key ID Sağlama](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id) ve [In-App Purchase Key Dosyası Yükleme](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file) bölümlerine bakın. 5. Bağlantıları ekibimizle [e-posta](mailto:support@adapty.io) aracılığıyla veya Adapty Kontrol Paneli'ndeki çevrimiçi sohbet üzerinden paylaşın. Geçmiş verilerin aktarılması, mevcut Adapty girdileriyle çakışsa bile yinelenen kayıtlar oluşturmaz. ## Android için bilinen kısıtlamalar \{#known-limitations-for-android\} 1. Yalnızca aktif abonelikler geri yüklenecektir; süresi dolmuş işlemler geri yüklenmez. 2. Bir abonelikteki yalnızca en son yenilemeler geri yüklenecektir; satın alma zincirinin tamamı geri yüklenmez. 3. Satın alma tarihinden bu yana ürün fiyatı değişmişse, mevcut fiyat kullanılır ve bu da yanlış fiyatlandırmaya yol açabilir. :::note Büyük hacimde Android işleminiz varsa, varsayılan API sınırını aşmamak için içe aktarmaya başlamadan önce [Google Play Developer API kota artışı talep etmeniz](google-play-quota-increase) gerekebilir. ::: ## İçe aktarma dosyası formatı \{#import-file-format\} :::tip RevenueCat'ten geçiş yapıyorsanız, RevenueCat dışa aktarma dosyasını doğrudan gönderebilirsiniz — dönüştürme gerekmez. Dışa aktarma talimatları için [RevenueCat belgelerine](https://www.revenuecat.com/docs/integrations/scheduled-data-exports) bakın. ::: Lütfen verilerinizi aşağıdaki kurallara uyan bir veya birden fazla dosyada hazırlayın: - [ ] Dosya formatı .CSV olmalıdır. - [ ] Android, iOS ve Stripe içe aktarmaları için ayrı dosyalar hazırlanmalıdır. - [ ] Her içe aktarma dosyası tüm [zorunlu sütunları](importing-historical-data-to-adapty#required-fields) içermelidir. - [ ] İçe aktarma dosyalarındaki sütunların başlıkları olmalıdır. - [ ] Sütun başlıkları aşağıdaki tablodaki **Column name** sütunuyla birebir aynı olmalıdır. Yazım hatalarını kontrol edin. - [ ] Zorunlu olmayan sütunlar dosyada bulunmayabilir. Verisini almadığınız alanlar için boş sütun eklemeyin. - [ ] İçe aktarma dosyaları tabloda belirtilmeyen ekstra sütunlar içermemelidir. Varsa lütfen silin. - [ ] Değerler virgülle ayrılmalıdır. - [ ] Değerler tırnak içine alınmamalıdır. - [ ] Bir kullanıcı için birden fazla **apple_original_transaction_id** varsa, her **apple_original_transaction_id** için ayrı satır olarak hepsini ekleyin. Aksi takdirde consumable satın almaları geri yükleyemeyebiliriz. Örnek dosyalar için lütfen [iOS](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_ios_sample.csv) ve [Android](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_android_sample.csv) bağlantılarını kullanın. ### Kullanılabilir içe aktarma dosyası sütunları \{#available-import-file-columns\} | Sütun adı | Varlık | Açıklama | |-----------|--------|-----------| | **user_id** | zorunlu | Kullanıcınızın kimliği | | **apple_original_transaction_id** | iOS için zorunlu | <p>Orijinal işlem kimliği veya OTID ([daha fazla bilgi](https://developer.apple.com/documentation/appstoreserverapi/originaltransactionid)), StoreKit 2 içe aktarma mekanizmasında kullanılır. Bir kullanıcının birden fazla OTID'i olabileceğinden, başarılı bir içe aktarma için en az birini sağlamak yeterlidir.</p><p></p><p>**Not:** Bu içe aktarmanın çalışması için Adapty Kontrol Paneli'nizde In-app purchase API kimlik bilgilerinin ayarlanmış olması gerekir. Nasıl yapacağınızı [buradan](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file) öğrenin.</p> | | **google_product_id** | Google için zorunlu | Google Play Store'daki ürün kimliği. | | **google_purchase_token** | Google için zorunlu | Kullanıcıyı ve satın aldıkları uygulama içi ürünün ürün kimliğini temsil eden benzersiz tanımlayıcı | | **google_is_subscription** | Google için zorunlu | Olası değerler: `1` \| `0` | | **stripe_token** | Stripe için zorunlu | Benzersiz bir satın almayı temsil eden Stripe nesnesinin token'ı. Stripe'ın Abonelik (`sub_...`) veya Ödeme Niyeti (`pi_...`) token'ı olabilir. | | **subscription_expiration_date** | isteğe bağlı | Abonelik bitiş tarihi, yani bir sonraki ödeme tarihi; saat dilimi bilgisiyle birlikte tarih ve saat (2020-12-31T23:59:59-06:00) | | **created_at** | isteğe bağlı | Profil oluşturma tarihi ve saati (2019-12-31 23:59:59-06:00) | | **birthday** | isteğe bağlı | Kullanıcının doğum tarihi, format: 2000-12-31 | | **email** | isteğe bağlı | Kullanıcınızın e-posta adresi | | **gender** | isteğe bağlı | Kullanıcının cinsiyeti | | **phone_number** | isteğe bağlı | Kullanıcınızın telefon numarası | | **country** | isteğe bağlı | [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) formatı | | **first_name** | isteğe bağlı | Kullanıcınızın adı | | **last_name** | isteğe bağlı | Kullanıcınızın soyadı | | **last_seen** | isteğe bağlı | Saat dilimi bilgisiyle birlikte tarih ve saat (2020-12-31T23:59:59-06:00) | | **idfa** | isteğe bağlı | Reklam verenler için tanımlayıcı (IDFA), Apple'ın kullanıcının cihazına atadığı rastgele bir cihaz tanımlayıcısıdır. Yalnızca iOS uygulamaları için geçerlidir | | **idfv** | isteğe bağlı | Satıcılar için tanımlayıcı (IDFV), tek bir geliştiricinin geliştirdiği tüm uygulamalara (bu durumda sizin uygulamalarınıza) atanan benzersiz bir koddur. Yalnızca iOS uygulamaları için geçerlidir | | **advertising_id** | isteğe bağlı | Reklam kimliği, reklamverenlerin bir kullanıcının cihazını benzersiz şekilde tanımlamak için kullanabileceği Android İşletim Sistemi tarafından atanan benzersiz bir koddur | | **amplitude_user_id** | isteğe bağlı | Amplitude'deki kullanıcı kimliği | | **amplitude_device_id** | isteğe bağlı | Amplitude'deki cihaz kimliği | | **mixpanel_user_id** | isteğe bağlı | Mixpanel'deki kullanıcı kimliği | | **appmetrica_profile_id** | isteğe bağlı | AppMetrica'daki kullanıcı profil kimliği | | **appmetrica_device_id** | isteğe bağlı | AppMetrica'daki cihaz kimliği | | **appsflyer_id** | isteğe bağlı | AppsFlyer'dan benzersiz tanımlayıcı | | **adjust_device_id** | isteğe bağlı | Adjust'taki cihaz kimliği | | **facebook_anonymous_id** | isteğe bağlı | Facebook'un, uygulamanız veya web sitenizle Facebook'a giriş yapmadan (anonim olarak) etkileşime giren kullanıcılar için oluşturduğu benzersiz tanımlayıcı | | **branch_id** | isteğe bağlı | Branch'ten benzersiz tanımlayıcı | | **attribution_source** | isteğe bağlı | Attribution'ın kaynak entegrasyonu, örneğin appsflyer | | **attribution_status** | isteğe bağlı | organic | | **attribution_channel** | isteğe bağlı | İşlemi getiren attribution kanalı | | **attribution_campaign** | isteğe bağlı | İşlemi getiren attribution kampanyası | | **attribution_ad_group** | isteğe bağlı | İşlemi getiren attribution reklam grubu | | **attribution_ad_set** | isteğe bağlı | İşlemi getiren attribution reklam seti | | **attribution_creative** | isteğe bağlı | Tıklama, dönüşüm veya yükleme gibi istenen eylemleri yönlendirmedeki etkinliklerini belirlemek için takip edilen bir reklam veya pazarlama kampanyasında kullanılan belirli görsel veya metinsel öğeler | | **custom_attributes** | isteğe bağlı | Anahtar-değer formatında JSON sözlüğü olarak en fazla 30 özel öznitelik tanımlayın: <ul><li>**key**: (string) Özel özniteliğin adı</li><li>**value**: (string, integer, float veya boolean) Özel özniteliğin değeri.</li></ul><p>Format: `"{'string_value': 'some_value', 'float_value': 123.0, 'int_value': 456}"`.</p><p>Formatta çift ve tek tırnak kullanımına dikkat edin. Boolean ve tam sayı değerlerinin float'a dönüştürüleceğini unutmayın.</p> | ### Zorunlu Alanlar \{#required-fields\} Her platform için 2 grup zorunlu alan vardır: **user_id** ve ilgili platforma özgü satın almaları tanımlayan veriler. Platform başına zorunlu alanlar için aşağıdaki tabloya bakın. | Platform | Zorunlu alanlar | |--------|---------------| | iOS | <p>user_id</p><p>apple_original_transaction_id</p> | | Android | <p>user_id</p><p>google_product_id</p><p>google_purchase_token</p><p>google_is_subscription</p> | | Stripe | <p>user_id</p><p>stripe_token</p> | Bu alanlar olmadan Adapty işlemleri getiremez. Doğru kohort analitiği için lütfen `created_at` alanını belirtin. Sağlanmazsa, yükleme tarihinin ilk satın alma tarihiyle aynı olduğu varsayılır. ### Verileri Adapty'ye Aktar \{#import-data-to-adapty\} Lütfen bizimle iletişime geçin ve içe aktarma dosyalarınızı [support@adapty.io](mailto:support@adapty.io) adresi veya [Adapty Kontrol Paneli](https://app.adapty.io/overview)'ndeki çevrimiçi sohbet aracılığıyla paylaşın. --- # File: migrate-integrations-to-adapty --- --- title: "Adapty'ye entegrasyonları taşıma" description: "Analytics ve attribution entegrasyonlarını eski bir çözümden Adapty'ye, etkinlikleri çoğaltmadan veya kampanyaları aksatmadan geçirin." --- Adapty'ye geçiş yapmak, yalnızca SDK'yı değiştirmekten fazlasını gerektirir. Amplitude ve Adjust gibi üçüncü taraf analytics ve attribution entegrasyonlarınızın da koordineli bir şekilde değiştirilmesi gerekir. Dikkatli yapıldığında, geçiş sırasında çok az sayıda tekrarlanan veya eksik etkinlik oluşur ve kampanyalarınız sekteye uğramaz. ## Etkinliklerinizi eşleştirin \{#map-your-events\} Etkinlik adları, çoğu Adapty entegrasyonunda özelleştirilebilir. Bunları kontrol panellerinizde ve kampanyalarınızda zaten kullanılan adlarla eşleşecek şekilde yapılandırabilirsiniz. Analytics ve kampanya raporlarınız, geçişin ardından aynı etkinlik adlarıyla çalışmaya devam eder. Adapty'de mevcut etkinliklerin tam listesini görmek için [Etkinlikler](events) sayfasına bakın. Adjust için entegrasyon, özel etkinlik adları yerine etkinlik ID'leri kullanır. Mevcut etkinlik ID'lerinizi Adjust kontrol panelinden Adapty entegrasyon yapılandırmasına aktarın. Ayrıntılar için [Adjust entegrasyon kılavuzuna](adjust) bakın. ## Adapty entegrasyon etkinliklerini nasıl oluşturur \{#how-adapty-creates-integration-events\} Bir entegrasyona etkinlik göndermek için Adapty'nin bir kullanıcı profiline sahip olması gerekir. Profil iki şekilde oluşturulur: - **Geçmiş veri içe aktarma**: [Geçmiş işlem verilerini içe aktardığınızda](importing-historical-data-to-adapty) SDK devreye girmeden önce profil oluşturulur. - **SDK etkileşimi**: Kullanıcı uygulamayı Adapty SDK'sı ile ilk kez açtığında profil otomatik olarak oluşturulur. Adapty, eski sistemde gerçekleştirilen satın almaları gerçek zamanlı olarak öğrenir. Ancak entegrasyon etkinliğini yalnızca satın alan kullanıcının profili mevcut olduğunda gönderebilir. Profil, kullanıcı uygulamayı Adapty SDK'sı ile açtığında oluşturulur. Yeni sürüme güncelleme yapmayan kullanıcılar entegrasyon etkinliği oluşturmaz. ## Geçiş gününden önce hazırlanın \{#prepare-before-migration-day\} ### Geçmiş etkinlikleri hariç tutun \{#exclude-historical-events\} [Entegrasyon ayarlarınızda](configuration) **Exclude Historical Events** seçeneğini etkinleştirin. Bu, kullanıcının ilk Adapty SDK oturumundan önceki etkinliklerin entegrasyona gönderilmesini engeller. Bu ayar özellikle [geçmiş veri içe aktarma](importing-historical-data-to-adapty) sırasında önemlidir; Adapty bu süreçte büyük hacimde geçmiş işlemi aynı anda işler. Bu ayar olmadan söz konusu işlemler, analytics aracınızda büyük hacimde etkinlik üretir. ### Entegrasyonu önceden kurun \{#set-up-the-integration-in-advance\} Adapty, bir entegrasyonu devre dışı tutarken yapılandırmanıza ve test etmenize olanak tanır. Entegrasyonu etkinleştirmeye hazır olana kadar kimlik bilgilerini, etkinlik eşleştirmeyi ve filtreleri ayarlayabilirsiniz. Kurulum, etkinleştirdiğinizde korunur; dolayısıyla geçiş gününe kadar kapalı tutmak hiçbir şeyi kaybettirmez. Entegrasyonunuzu bulmak için [Attribution entegrasyonları](attribution-integration), [Analytics entegrasyonları](analytics-integration), [Mesajlaşma servisi entegrasyonları](messaging) veya [Webhook ve ETL entegrasyonları](webhook-and-etl) sayfalarına bakın. ## Geçiş günü değişikliği yapın \{#switch-on-migration-day\} Eski çözümünüzdeki entegrasyonu devre dışı bırakın ve aynı anda Adapty'deki entegrasyonu etkinleştirin. Her ikisini aynı anda çalıştırmak tekrarlanan etkinliklere neden olur. Geçiş günü büyük kullanıcı edinme kampanyalarını duraklatın. Bu, örtüşme penceresi boyunca oluşan etkinliklerin neden olabileceği kampanya optimizasyon hatalarının riskini azaltır. ## Ne beklemelisiniz \{#what-to-expect\} Geçiş sırasında bazı eksik veya tekrarlanan entegrasyon etkinlikleri kaçınılmazdır. Geçiş doğru yapıldığında, etkilenen etkinliklerin sayısı göz ardı edilebilecek düzeyde azdır. Boşlukların temel kaynağı yukarıda açıklanan zamanlama sorunudur: Adapty, bir satın alma için entegrasyon etkinliğini ancak kullanıcının profili mevcut olduktan sonra gönderebilir. Eski sistemde yapılan satın almalar, alıcı uygulamayı Adapty SDK'sı ile açana kadar Adapty entegrasyon etkinliği oluşturmaz. ## Entegrasyonlar ve sunucudan sunucuya bildirimler \{#integrations-vs-server-to-server-notifications\} Adapty, ham sunucudan sunucuya mağaza bildirimlerini doğrudan analytics veya attribution araçlarınıza yönlendirmek yerine entegrasyonları kullanmanızı önerir. Entegrasyonlarla: - **Birleşik format**: App Store, Google Play, Stripe gibi tüm mağazalardan gelen etkinlikler aynı etkinlik formatını kullanır. - **Zenginleştirilmiş veri**: Etkinlikler, abonelik durumu ve kullanıcı öznitelikleri gibi Adapty'nin topladığı verileri içerir. Ham bildirimler bunu içermez. --- # File: whats-new --- --- title: "Neler yeni" description: "Adapty'deki en son özellikler ve geliştirmelerden haberdar olun" --- En son özellikler, geliştirmeler, SDK güncellemeleri ve uygulamanızın para kazanma stratejisini optimize etmenize yardımcı olan dokümantasyon iyileştirmeleri hakkında bilgi edinin. Bu sayfa her ay en önemli sürümleri öne çıkarır. :::note Yeni özellikler hakkında geri bildiriminiz mi var? Sizden duymaktan mutluluk duyarız! [Ürün geri bildirim panosu](https://adapty.featurebase.app/en?b=69831ba5e82e7a3391632ec2) aracılığıyla bizimle iletişime geçin. ::: ## Temmuz 2026 \{#july-2026\} - **Sanal para birimleri**: Token, coin veya gem gibi uygulama içi para birimlerini tanımlayın, her kullanıcı için bakiye atayın ve takip edin; bu bakiyeleri sunucu tarafı API üzerinden okuyun. [Daha fazla bilgi](virtual-currencies) - **Apple Ads Manager'da AI Agent**: Apple Ads performansınızı danışmanlık sohbet aracısına sorun ve kampanya verilerinizden elde edilen yanıtları elle rapor oluşturmak zorunda kalmadan alın. [Daha fazla bilgi](ads-manager-ai-agent) - **Apple Ads Manager'da yeni otomasyonlar**: Mevcut anahtar kelime ve arama terimi otomasyonlarının yanı sıra iki yeni kural türüyle kampanya ve reklam grubu düzeylerinde değişiklikleri otomatikleştirin. [Kampanya kuralları](ads-manager-automations-campaign-rules) | [Reklam grubu kuralları](ads-manager-automations-ad-group-rules) - **Adapty Mail'de profiller**: Her kullanıcının yolculuğunu, mevcut abonelik durumunu ve abonelikten çıkma durumunu tek bir yerde gösteren aboneye özel görünüm. [Daha fazla bilgi](mail-profiles) - **React Native, Flutter, Capacitor ve Kotlin Multiplatform için SDK v4**: Flow'ları destekleyen v4 SDK'lar yayında. React Native, Flutter ve Capacitor genel kullanıma sunuldu; Kotlin Multiplatform v4 de kendi geçiş rehberiyle birlikte çıktı. [React Native](migration-to-react-native-sdk-v4) | [Flutter](migration-to-flutter-sdk-v4) | [Capacitor](migration-to-capacitor-sdk-v4) | [Kotlin Multiplatform](migration-to-kmp-sdk-v4) - **Yeni webhook alanları**: Webhook payload'ları artık her işlem için orijinal fiyatı ve indirimi içeriyor; böylece promosyon ve başlangıç fiyatlandırmasını aşağı akışta takip edebilirsiniz. Bu alanlar yalnızca webhook'larda mevcuttur. [Daha fazla bilgi](webhook-event-types-and-fields) - **Flow'larda üstü çizili fiyatlar**: İndirim rozeti ile birlikte indirimli fiyatın yanında orijinal fiyatı üstü çizili olarak doğrudan Flow Builder'da gösterin. [Daha fazla bilgi](strikethrough-price) - **Flow şablon galerisi**: Boş bir tuvalle başlamak yerine, profesyonelce tasarlanmış bir şablondan yeni bir flow başlatın ve uygulamanıza uyacak şekilde özelleştirin. [Daha fazla bilgi](paywall-builder-templates) - **Install tools butonu**: Artık her dokümantasyon makalesinin başlığında bir **Install tools** butonu bulunuyor. Bu buton, Adapty SDK entegrasyon becerisini Claude Code, Copilot CLI, Gemini CLI, Codex ve diğer yapay zeka kodlama asistanlarına yüklemek için kopyalamaya hazır komutlar içeren bir modal açar. [Daha fazla bilgi](adapty-sdk-integration-skill) - **Yeni Unity SDK kurulum yöntemi**: Unity SDK'yı artık Swift Package Manager üzerinden kurabilirsiniz; yaygın kurulum sorunları için sorun giderme rehberi de eklendi. [Daha fazla bilgi](sdk-installation-unity) - **Flow Builder'da alt bilgi konteyneri**: Ekranın geri kalanı kaydırılırken sabit kalan yapışkan bir alt panel — CTA butonları, yasal metinler ve bağlantılar için idealdir. [Daha fazla bilgi](builder-containers#footer) - **Yeni Flow Builder video eğitimleri**: Flow Builder kılavuzlarına eklenen, flow oluşturmaya yönelik adım adım YouTube video oynatma listesi. [Daha fazla bilgi](adapty-flow-builder) ## Haziran 2026 \{#june-2026\} - **Flow'lar artık Android'i destekliyor**: Paywall ve onboarding'ler için görsel no-code builder artık iOS'un yanı sıra Android SDK v4 ve üzerinde de çalışıyor. Ekranlar, web görünümü olmadan yerel olarak render ediliyor. [Daha fazla bilgi](adapty-flow-builder) - **Apple Ads Manager'da CPP A/B Testleri**: Özel ürün sayfalarını Apple Ads içinde birbirleriyle karşılaştırın. Mevcut varsayılan sayfanız dahil 2 ila 4 sayfa seçin; Apple Ads aralarındaki trafiği döngüsel olarak dağıtır ve hangisinin en iyi dönüşüm sağladığını raporlar. [Daha fazla bilgi](ads-manager-cpp-ab-tests) - **Adapty Mail API**: Kullanıcı profillerini ve işlemleri, Adapty SDK üzerinden yönlendirmeden doğrudan sunucunuzdan Adapty Mail'e gönderin. Abone tabanı oluşturmak, diğer uygulamalarınızdaki aboneleri yeniden kullanmak veya backend'inizi gerçeğin kaynağı olarak tutmak için kullanabilirsiniz. [Daha fazla bilgi edinin](mail-send-data-via-api) - **İlk açılışta Apple Ads hedefli paywall gösterme**: Apple Ads attribution verisi SDK etkinleştikten sonra geldiği için çok erken istenen bir paywall, Apple Ads kitlenizi kaçırır. Attribution verisi gelir gelmez Apple Ads hedefli paywallı göstermek için `AdaptyProfile.appliedAttributionSources` kullanın. [iOS](ios-show-aa-targeted-paywall) | [React Native](react-native-show-aa-targeted-paywall) | [Capacitor](capacitor-show-aa-targeted-paywall) - **Flow Builder'da Otomatik Kaydetme**: Flow Builder artık ilerlemenizi dakikada bir otomatik olarak kaydediyor; böylece sayfadan ayrıldığınızda kaydedilmemiş çalışmalarınızı kaybetmiyorsunuz. **Cmd/Ctrl + S** kısayoluyla taslağı manuel olarak da kaydedebilirsiniz. [Daha fazla bilgi](builder-save-publish) - **Yeni Flow Builder video eğitimleri**: İki yeni rehber; flow ekranları arasında gezinme oluşturmayı ve seçili, etkin ve devre dışı gibi element durumlarını tasarlamayı ele alıyor. [Flow'larda gezinme](onboarding-navigation-branching) | [Element durumları](builder-element-states) - **Japonca ve Vietnamca Dokümantasyon**: Adapty dokümantasyonu artık Japonca (日本語) ve Vietnamca (Tiếng Việt) dillerinde de mevcut. Dil değiştirmek için üst navigasyondaki dil seçicisini kullanın. ## Mayıs 2026 \{#may-2026\} - **Flow'lar (Beta)**: Görsel bir no-code builder'da ekran dizileri oluşturun — tek ekranlı paywall'lar, çok adımlı onboarding'ler ve bunların arasındaki her şey, hepsi tek bir flow içinde. Ekranlar web view kullanmadan native olarak render edilir; uygulama güncellemesi yayınlamadan metin, tasarım ve mantığı güncelleyebilirsiniz. Şu an iOS, Android, React Native, Flutter ve Capacitor SDK v4 ve üzerini desteklemektedir. [Daha fazla bilgi](adapty-flow-builder) - **Autopilot artık test sonuçlarınıza göre uyum sağlıyor**: Yapay zeka büyüme yöneticisi gibi davranarak her tamamlanan turdan sonra büyüme planını günceller. Bir sonraki hipotez, hangi deneyleri yürüttüğünüze, hangilerinin kazandığına ve hangi yönlerin hâlâ keşfedilmeye değer olduğuna dayanır — sabit bir sırayı takip etmek yerine. [Daha fazla bilgi edinin](autopilot-how-it-works#how-ai-growth-advisor-decides-what-to-recommend) - **Autopilot Market Insights'ta Aktivasyon ARPU'su**: Yeni bir grafik, uygulamanızın yeni kurulum başına ortalama gelirini kategori ortalamasıyla karşılaştırır. Dönüşüm hunisiyle birlikte değerlendirin — yüksek dönüşümle birlikte düşük Aktivasyon ARPU'su, fiyatlandırmanın düşük tutulduğuna işaret edebilir. [Daha fazla bilgi](autopilot-analysis#activation-arpu) - **Adapty Mail'de Analytics**: Her kampanya için teslimat metriklerini ve e-postaya atfedilen geliri tek bir görünümde karşılaştırın. Kampanya, segment, A/B varyantı, mesaj veya tetikleyiciye göre gruplandırın, detaylandırın ve filtreleyin; ardından herhangi bir satıra tıklayarak derinlemesine inceleyin. [Daha fazla bilgi](mail-analytics) - **Adapty Mail'deki marka profili**: E-posta içeriğini, tonunu, görsellerini ve web paywall içeriğini yönlendiren birleşik bir profil. Adapty, bu profili uygulamanızın mağaza sayfasından, açılış sayfasından, yasal sayfalarından ve sosyal profillerinizden oluşturur; her bölümü satır içinde inceleyip düzenleyebilirsiniz. [Daha fazla bilgi](mail-brand) - **Adapty UA'da Tahminler**: Her kohort için tahmini gelir, ROAS, reklam kârı, ARPU ve ARPPU; böylece kampanyalarınız olgunlaşmadan önce karşılaştırabilirsiniz. Tahminler, uygulamanızın kendi geçmiş kohort verilerinden oluşturulur, günlük güncellenir ve D0'dan D360'a kadar veya özel bir gün için kohort dönemlerinde kullanılabilir. [Daha fazla bilgi](ua-predicted-metrics) - **Adapty UA özel S3 dışa aktarımında yeni alanlar**: Özel S3 dışa aktarımı artık `bundle_id`, `device_brand`, `device_model`, `os_version`, `app_version` ve `sdk_version` alanlarını içeriyor. Attribution verilerini aşağı akışta cihaz ve uygulama sürümüne göre dilimleyin ve birleştirin. [Daha fazla bilgi](ua-custom-s3) - **CLI'da Placement kitleleri**: `adapty placements create` ve `adapty placements update` komutları artık `--audiences` bayrağını destekliyor — `{segment_ids, paywall_id, priority}` girdilerinden oluşan bir JSON dizisi — böylece terminalden farklı segmentlere farklı paywalllar hedefleyebilirsiniz. Yeni `adapty paywalls placements` komutu, belirli bir paywall'ı kullanan tüm placement'ları listeler; böylece paywall'ı değiştirmeden önce etkisini önizleyebilirsiniz. [Daha fazla bilgi](developer-cli-reference#placements) - **İspanyolca Dokümantasyon**: Adapty dokümantasyonu artık İspanyolca (Español) olarak da mevcut. Dil seçicisini üst navigasyondan kullanarak diller arasında geçiş yapabilirsiniz. ## Nisan 2026 \{#april-2026\} - **Adapty Mail**: Deneme kullanıcılarını ücretli abonelere dönüştüren yapay zeka destekli e-posta kampanyaları. Kampanyalarınızı Adapty projenizden oluşturun, gönderin ve ilişkilendirin — ayrı bir e-posta platformuna gerek yok. [Daha fazla bilgi](adapty-mail) - **Autopilot'ta Paywall Tanılama**: Test oluşturmadan önce paywallınızda neyi düzeltmeniz gerektiğini öğrenin. Bir ekran görüntüsü yükleyin; Autopilot, kategorinizdeki en iyi performans gösteren uygulamalardan referans alınmış öneriler ve yapay zeka tarafından üretilen düzen ile metin önerileri sunar. Referans alınan öneriler, büyüme planınızdaki A/B testi turlarına dönüşür. [Daha fazla bilgi edinin](autopilot-analysis#paywall-analysis) - **Her Autopilot önerisi için daha net rehberlik**: Her hipotez artık neden önemli olduğunu (paywall'ınızın yerleşik kalıplardan nasıl saptığına dair veriye dayalı bir açıklama), neyi değiştireceğinizi ve A/B testini nasıl kuracağınızı, ayrıca yeni "Sonuçlarınızı nasıl yorumlarsınız" bölümünde hangi metrikleri izleyeceğinizi açıkça ortaya koyuyor. [Daha fazla bilgi edinin](autopilot-execute-plan#step-1-view-the-hypothesis) - **Autopilot büyüme planınızı güncel tutun**: En son pazar verilerini ve yeni önerileri çekmek için analizi yenileyin; yeni öneriler işe yaramazsa sürüm geçmişindeki eski önerilere geri dönün. Hipotezler Üst öncelik, Tümü, Fiyatlandırma, Görsel, Coğrafi fiyatlandırma ve Arşivlenenler sekmeleri altında gruplandırılmıştır. [Daha fazla bilgi edinin](autopilot-growth-plan) - **Autopilot'ta süreye göre gelir dağılımı**: Gelirinizin tek bir abonelik süresinde aşırı yoğunlaşıp yoğunlaşmadığını görün. Yeni bir Market Insights grafiği, kategori ve ülkenize ait sektör ortalamasıyla birlikte süreye göre gelir karışımınızı gösterir. [Daha fazla bilgi](autopilot-analysis#revenue-distribution-by-duration) - **Güncellenmiş LTV ve gelir tahminleri**: Tahmini LTV ve gelir artık yeterli geçmiş veri olduğunda uygulamanızın kendi kohort elde tutma verilerini, yoksa uygulamalar arası ortalamaları kullanıyor; böylece daha yeni uygulamalar bile analitik ve A/B testlerinde kullanılabilir tahminler elde ediyor. [Daha fazla bilgi](predicted-ltv-and-revenue) - **Adapty UA'da tüm etkinlikleri gönder**: Meta ve TikTok'a daha kapsamlı bir dönüşüm görünümü sunarak kitle modellemesini keskinleştirin. Adapty artık yalnızca bir kampanyayla eşleşen kullanıcılar için değil, organik ve attribution yapılmamış kullanıcılardan gelen yükleme ve işlemleri de pikselinize iletmeyi destekliyor. [Meta](ua-facebook#send-all-events) | [TikTok](ua-tiktok#send-all-events) - **Rusça ve Türkçe dokümantasyon**: Adapty dokümantasyonu artık Rusça (Русский) ve Türkçe (Türkçe) olarak kullanılabilir. Dil seçimi için üst gezinti çubuğundaki dil seçiciyi kullanabilirsiniz. ## Mart 2026 \{#march-2026\} - **Geliştirici CLI'ı**: Adapty hesabınızı kontrol panelini açmadan terminalden yönetin. CLI sayesinde uygulama oluşturabilir, access level tanımlayabilir, ürün kurabilir, paywall oluşturabilir ve placement yapılandırabilirsiniz — tüm bunlar otomatik ortamlar için betiklenebilir. AI kodlama asistanlarının CLI ile çalışmasına yardımcı olmak için bir [Adapty CLI becerisi](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) de mevcuttur. [Daha fazla bilgi](developer-cli) - **Apple Ads Manager'daki Genel Bakış sayfası**: Tüm temel Apple Ads metriklerini tek bir yerde, her biri bir trend grafiğiyle görün. Başlık açılır menüsünden uygulamaya göre filtreleyin, hangi metriklerin görüneceğini özelleştirin ve grafik türü ile gelir görünümünü ayarlayın. [Daha fazla bilgi](ads-manager-overview) - **Apple Ads Manager'da Market Intelligence**: Rakiplerinizin 50'den fazla ülkede hangi anahtar kelimelerde reklam yayınladığını görün ve en iyi performans gösteren anahtar kelimeleri doğrudan kampanyalarınıza ekleyin. [Daha fazla bilgi](ads-manager-market-intelligence) - **Apple Ads Manager'da tam döngülü anahtar kelime otomasyonları**: Tanımladığınız performans kurallarına göre teklifleri otomatik olarak ayarlayın, anahtar kelimeleri durdurun veya etkinleştirin ve bunları reklam grupları arasında taşıyın. [Daha fazla bilgi](ads-manager-automations-keyword-rules) - **Apple Ads Manager'da teklif geçmişi**: Herhangi bir anahtar kelimenin CPT teklifi için tam değişiklik günlüğünü görüntüleyin — her değişikliğin ne zaman gerçekleştiğini, önceki ve yeni değerleri ve hangi otomasyon kuralının tetiklediğini öğrenin. [Daha fazla bilgi](ads-manager-manage-keywords#bid-history) - **Autopilot'ta görsel turlar**: Paywall tasarım önerileri artık büyüme planınızda birinci sınıf turlar — monetizasyon turlarının yanında kenar çubuğunda listeleniyor. Her görsel tur, bir tasarım maketini, kalıbın en iyi ne zaman işe yaradığının açıklamasını ve hedeflediği temel metrikleri içeriyor. [Daha fazla bilgi edinin](autopilot-growth-plan#view-the-growth-plan) - **Autopilot'a kendi hipotezinizi ekleyin**: Büyüme planınızı özel turlarla genişletin. Bir başlık, açıklama, tur türü (monetizasyon veya görsel), hedef metrikler ve — monetizasyon turları için — dahil olan ürünleri ekleyin. [Daha fazla bilgi](autopilot-growth-plan#add-your-own-hypothesis) - **Autopilot turlarını yeniden sıralayın**: Büyüme planınızın aşamalarını sürükleyip sıralayarak deneyleri stratejinize en uygun sırayla çalıştırın. [Daha fazla bilgi](autopilot) - **Autopilot'ta Coğrafi Fiyatlandırma Turları**: Büyüme planınızda yeni bir tur türü olarak ülkeye özel fiyat değişikliklerini test edin. Market Insights verilerine dayanarak Autopilot, her ülkede fiyatların artırılması, düşürülmesi veya sabit tutulması gerektiğini önerir. Bir öneriyi A/B testi olarak çalıştırmak için coğrafi fiyatlandırma turu olarak ekleyin — aynı anda en fazla 5 tur çalışabilir. [Daha fazla bilgi](autopilot-growth-plan#geo-pricing-hypotheses) - **Apple Ads Manager'da arama terimi otomasyonları**: Kazanan arama terimlerini tam eşleşme anahtar kelimelere otomatik olarak yükseltin ve manuel rapor indirmeye gerek kalmadan kaynakta negatifleyin. Kurallar şablonlardan oluşturulabilir ya da özel koşullar ve zamanlamalarla sıfırdan inşa edilebilir. [Daha fazla bilgi](ads-manager-automations-search-terms) - **Apple Ads Manager'da Maximize Conversions teklif stratejisi**: Kampanya oluştururken artık teklif stratejisi olarak Maximize Conversions'ı seçebilirsiniz. Apple'ın algoritması, isteğe bağlı bir hedef EBM rehberliğinde bütçeniz dahilinde indirmeleri maksimuma çıkarır. [Daha fazla bilgi](ads-manager-create-campaign) - **Adapty UA'da FunnelFox entegrasyonu**: Adapty UA'da FunnelFox ile yeni entegrasyon artık kullanılabilir. [FunnelFox](ua-funnelfox) - **Çince dokümantasyon**: Adapty dokümantasyonu artık Çince (中文) olarak da mevcut. Üst gezinti çubuğundaki dil seçicisini kullanarak diller arasında geçiş yapabilirsiniz. ## Şubat 2026 \{#february-2026\} - **Ülkeye özgü ürün fiyatlandırması**: Adapty Kontrol Paneli üzerinden her ülke için ayrı fiyat belirleyin — Adapty değişiklikleri App Store Connect ve Google Play'e otomatik olarak yansıtır. Her fiyat güncellemesi denetim günlüğüne kaydedilir, hiçbir değişiklik takip dışı kalmaz. [Daha fazla bilgi](edit-product) - **Autopilot'ta ülke bazında rakip fiyatlandırması**: Abonelik fiyatlarınızı en büyük pazarlarınızdaki rakiplerinizle karşılaştırın. [Daha fazla bilgi](autopilot-analysis#market-and-competitor-analysis) - **Onboarding versiyon kontrolü**: Tam versiyon geçmişiyle onboarding'lerinizin versiyonlarını takip edin ve yönetin. Değişiklikleri inceleyin ve gerektiğinde geri alın. - **Analizlerde paywall dönüşüm grafikleri**: Paywall görüntüleme → Deneme ve Paywall görüntüleme → Ücretli olmak üzere iki yeni dönüşüm grafiği, paywall'larınızın ziyaretçileri aboneye ne kadar dönüştürdüğünü gösterir. [Daha fazla bilgi](analytics-conversion) - **Yinelenen segmentler**: Benzer bir segmenti sıfırdan yeniden oluşturmak yerine, mevcut bir segmenti tüm filtreleriyle kopyalayın. Birden fazla kampanya veya örtüşen kitlelere sahip A/B testleri yürütürken kullanışlıdır. [Daha fazla bilgi](segments#duplicate-segments) - **Adapty mobil uygulamasında push bildirimleri**: Abonelik etkinliğini takip etmek için kontrol panelini açmadan, doğrudan Adapty iOS uygulamasında 14 etkinlik türü için push bildirimlerini yapılandırın. [Daha fazla bilgi](push-notifications) - **Kotlin Multiplatform SDK 3.15**: Onboarding desteği, web paywalls ve API iyileştirmeleri ekler. [Daha fazla bilgi](migration-to-kmp-315) - **Capacitor SDK 3.16**: Capacitor 8 desteği ekler. Capacitor 7 kullanan projeler SDK v3.15'te kalmalıdır. [Daha fazla bilgi](migration-to-capacitor-316) - **LLM destekli SDK entegrasyon rehberleri**: AI kodlama asistanlarının yardımıyla Adapty entegrasyonu için adım adım rehberler. Her rehber, LLM'inizi kontrol paneli kurulumundan satın almalara kadar tüm implementasyon sürecinde yönlendirir. [iOS](adapty-cursor) | [Android](adapty-cursor-android) | [React Native](adapty-cursor-react-native) | [Flutter](adapty-cursor-flutter) | [Unity](adapty-cursor-unity) | [Kotlin Multiplatform](adapty-cursor-kmp) | [Capacitor](adapty-cursor-capacitor). Tek komutlu otomatik bir flow için yeni **adapty-sdk-integration skill**'i deneyin (beta): [iOS](adapty-sdk-integration-skill) | [Android](adapty-sdk-integration-skill-android) | [React Native](adapty-sdk-integration-skill-react-native) | [Flutter](adapty-sdk-integration-skill-flutter) | [Unity](adapty-sdk-integration-skill-unity) | [Kotlin Multiplatform](adapty-sdk-integration-skill-kmp) | [Capacitor](adapty-sdk-integration-skill-capacitor) ## Ocak 2026 \{#january-2026\} - **Capacitor SDK resmi olarak yayınlandı**: Kapsamlı testlerin ardından Capacitor SDK artık production kullanımına hazır. Capacitor kullanarak iOS ve Android için abonelik uygulamaları oluşturun; tam Adapty entegrasyon desteğinden yararlanın. [Daha fazla bilgi](capacitor-sdk-overview) - **Yeni uygulamalar için Autopilot**: Autopilot analizi, uygulamanızın henüz kapsamlı bir işlem geçmişi olmasa bile artık kullanılabilir. Veriye dayalı fiyat optimizasyonu önerileri alın ve büyüme planınızı ilk günden oluşturun. [Daha fazla bilgi](autopilot) - **Autopilot'ta küresel fiyatlandırma fırsatları**: En iyi performans gösteren pazarlarınızdaki gelir potansiyelini ülkeye özgü fiyatlandırma önerileriyle keşfedin. Autopilot, sonraki en iyi 5 ülkeniz için dönüşüm oranlarını ve satın alma gücünü analiz ederek Adapty Pricing Index'e dayalı olarak fiyatları artırma, düşürme veya koruma konusunda veri odaklı öngörüler sunar. [Daha fazla bilgi](autopilot) - **Faturalama kurtarma dönüşüm metrikleri**: Yeni analitik grafikler, faturalama sorunlarından ve ek sürelerden kurtarılan geliri takip eder. Elde tutma kurtarma çabalarınızı ölçmek için "Billing issue converted", "Billing issue converted revenue", "Grace period converted" ve "Grace period converted revenue" metriklerini izleyin. - **Apple Ads Manager'da doğrudan reklam yönetimi**: Apple Ads kampanyalarınızı platformlar arasında geçiş yapmadan doğrudan Adapty içinde oluşturun ve yönetin. [Daha fazla bilgi](ads-manager-manage-ads) - **Apple Ads Manager analytics**: Adapty içinde detaylı reklam düzeyinde performans metrikleri ve attribution verilerine erişin. Kampanya performansını, reklam grubu analizlerini ve attribution içgörülerini tek bir kontrol panelinde görüntüleyin. [Daha fazla bilgi](adapty-ads-manager-analytics) - **Apple Ads attribution grafikleri**: Birden fazla attribution metriğini özelleştirilebilir grafiklerde birleştirerek Apple Ads performansınızı abonelik verileriyle birlikte analiz edin. [Daha fazla bilgi](adapty-ads-manager-analytics#charts) - **Apple Ads attribution segmentleri**: Apple Ads attribution verileriyle, iki tıkla segment oluşturun. Kampanya, reklam grubu veya anahtar kelimeye göre kullanıcıları hedefleyerek daha hassas analizler ve deneyler yapın. [Daha fazla bilgi](ads-manager-create-segments) - **Yeni dokümantasyon platformu**: Dokümantasyon sitesi yeni bir platforma taşındı. Bu sayede daha hızlı özellik güncellemeleri sunuluyor; geliştirilmiş arama, gezinme ve içerik düzeniyle kullanıcı deneyimi de iyileştirildi. ## Aralık 2025 \{#december-2025\} - **Apple Ads Manager dokümantasyonu**: Apple Search Ads kampanya verilerinizi gelir metrikleriyle tek bir analitik kontrol panelinde birleştirin. Yeni dokümantasyon; kampanya oluşturma, reklam grubu yönetimi ve reklam harcaması ROI'nizi abonelik performansıyla birlikte takip etmenin yollarını ele alıyor. [Daha fazla bilgi edinin](ads-manager) - **Uygulama içi web paywallları**: Web tabanlı paywallları, harici yönlendirme olmadan sorunsuz bir deneyim sunmak amacıyla uygulama içi tarayıcı üzerinden görüntüleyin. [iOS](ios-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Android](android-web-paywall#open-web-paywalls-in-an-in-app-browser) | [React Native](react-native-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Flutter](flutter-web-paywall#open-web-paywalls-in-an-in-app-browser) - **Rolling segmentler**: Hareketli zaman pencerelerine göre otomatik güncellenen dinamik kitle segmentleri oluşturun. Örneğin, "son 7 günde uygulamayı yükleyen kullanıcılar" için sürekli yenilenen ve en yeni müşterilerinizi her zaman gösteren bir segment oluşturabilirsiniz. [Daha fazla bilgi](segments#available-attributes) - **Meta ve TikTok kampanya kurulum kılavuzları**: Meta (Facebook & Instagram) ve TikTok'ta kampanya oluşturmak ve takip etmek için dönüşüm takibi ve analitik entegrasyonuyla birlikte adım adım dokümantasyon. [Meta](meta-create-campaign) | [TikTok](tiktok-create-campaign) - **Manuel paywall uygulama hızlı başlangıç kılavuzları**: Adapty SDK'yı özel paywall arayüzünüze nasıl entegre edeceğinizi adım adım anlatan hızlı başlangıç kılavuzlarıyla uygulama içi satın almaları daha hızlı hayata geçirin. [iOS](ios-implement-paywalls-manually) | [Android](android-implement-paywalls-manually) | [React Native](react-native-implement-paywalls-manually) | [Flutter](flutter-implement-paywalls-manually) | [Unity](unity-implement-paywalls-manually) | [Kotlin Multiplatform](kmp-quickstart-manual) | [Capacitor](capacitor-quickstart-manual) - **Onboarding linkleri için uygulama içi tarayıcı**: Onboarding'lerdeki harici linkler artık varsayılan olarak uygulama içi tarayıcıda açılıyor; böylece kullanıcılar uygulamanızdan çıkmıyor. İsterseniz bu davranışı harici tarayıcı kullanacak şekilde özelleştirebilirsiniz. [iOS](ios-present-onboardings#customize-how-links-open-in-onboardings) | [Android](android-present-onboardings#customize-how-links-open-in-onboardings) | [React Native](react-native-present-onboardings#customize-how-links-open-in-onboardings) - **Geliştirilmiş Autopilot önerileri**: Autopilot artık abonelik verilerinizin daha kapsamlı analizine dayalı olarak daha iyi fiyat optimizasyonu önerileri sunuyor. [Autopilot'u deneyin](autopilot) - **Dokümantasyon karanlık modu**: Dokümanlar artık sistem tercihinizi otomatik algılayan veya sağ üstteki düğmeyle manuel olarak geçiş yapabileceğiniz karanlık modu destekliyor. --- # File: adapty-ecosystem --- --- title: "Adapty ekosistemi" description: "Adapty, mobil uygulamalar için bir uygulama içi satın alma platformudur. Her ürünün ne yaptığını ve nasıl birbirine bağlandığını öğrenin." --- Adapty, mobil uygulamalar için bir uygulama içi satın alma platformudur ve tek bir misyon etrafında inşa edilmiştir: uygulamaları kârlı hale getirmek. Gelir büyütmek için ihtiyacınız olan her şeyi sunar: kullanıcı kazanın, onları dönüştürün, aboneliklerini sürdürün ve ayrılanları geri kazanın. Tek bir kayıt, ilk günden itibaren tüm Adapty ekosistemine erişim sağlar. Ürünler arasında geçiş yapmak için Adapty logosuna tıklamanız yeterli: - **Core** — StoreKit veya Google Play Billing'e dokunmadan satın almaları işleyin, kodsuz paywall'lar tasarlayın ve geliri gerçek zamanlı takip edin. Diğer ürünler bu temelin üzerine inşa edilmiştir. - **Adapty Ads Manager** — gerçek abonelik gelirine göre ölçümlenerek Apple Ads kampanyalarını yönetin ve optimize edin. - **Adapty Attribution** — herhangi bir MMP gerektirmeden hangi reklam kanallarının gerçekten gelir getirdiğini görün. - **Adapty Mail** — otomatik e-postalarla deneme süresi kullananları dönüştürün ve kaybettiğiniz kullanıcıları geri kazanın. **FunnelFox** (web'den uygulamaya funneller ve hosted checkout) ve **Adapty Finance** (gelecekteki abonelik gelirlerine karşı avans) olmak üzere iki ürün daha temel dördünün yanında yer alıyor. ## Ürünler birbirine nasıl bağlanır? \{#how-the-products-fit-together\} Her ürün, müşteriyle yaşam döngüsünün farklı bir noktasında temas kurar. Bağlantılı herhangi bir özelliğin üzerine gelerek hızlı bir tanım görebilir ya da tıklayarak belgelerine ulaşabilirsiniz. <ProductMap /> :::link Ayrıca bkz.: [Adapty benim için doğru mu?](is-adapty-right-for-me) ::: ## Yapay zeka iş akışları için tasarlandı \{#built-for-ai-workflows\} Adapty'yi yapay zeka kodlama ajanından çalıştırın — düzenleyicinizden çıkmadan entegre edin, yönetin ve referans alın. Ajanı platformunuza ait [SDK entegrasyon becerisine](adapty-sdk-integration-skill) yönlendirin; tek bir komutla tüm kurulumu tamamlasın. Ya da her adımı kendiniz incelemek için [adım adım LLM kılavuzunu](adapty-cursor) takip edin. Yapay zeka aracınız dokümanları istediğiniz şekilde çekebilir. **LLM için Kopyala** butonuyla herhangi bir sayfayı Markdown olarak kopyalayın ya da aracı tüm doküman setinin haritası olan [`llms.txt`](https://adapty.io/docs/tr/llms.txt) dosyasına yönlendirin. Canlı erişim için [Context7](https://context7.com/adaptyteam/adapty-docs) MCP sunucusu, Cursor, Claude Code ve diğer IDE'lerde dokümanlardan en alakalı kod parçacıklarını sunar. Tüm giriş noktaları için [Adapty'yi Yapay Zeka ile Yönetin](manage-adapty-with-ai) sayfasına bakın. ## Temel \{#core\} Temel, Adapty platformunun çekirdeğidir. Paywall'larınızı sunar, satın almaları yönetir ve sonrasında neler olduğunu ölçer. ### SDK'lar ve mağazalar \{#sdks-and-stores\} Ödeme altyapısıyla uğraşmayı unutun. Adapty, satın alma işlemlerini, makbuz doğrulamasını ve yenilemeleri sizin adınıza yönetir; her abonelin durumunu gerçek zamanlı olarak güncel tutar — böylece kimin erişimi olduğunu ve nedenini her zaman bilirsiniz. Uygulamanızın içinde, [Mobil SDK'lar](installation-of-adapty-sdks) satın alma akışını baştan sona yönetir ya da halihazırda bir ödeme sisteminiz varsa [mevcut billing'inizi gözlemler](observer-vs-full-mode). 7 platformu destekler: [iOS](ios-sdk-overview), [Android](android-sdk-overview), [React Native](react-native-sdk-overview), [Flutter](flutter-sdk-overview), [Unity](unity-sdk-overview), [Kotlin Multiplatform](kmp-sdk-overview) ve [Capacitor](capacitor-sdk-overview). Sunucu tarafında Adapty, mağazalara doğrudan bağlandığından her yenileme, iade ve ödeme sorunu size gerçek zamanlı olarak ulaşır — uygulama kapalı olsa bile. Desteklenenler: [App Store](initial_ios), [Google Play](initial-android), [Stripe](stripe) ve [Paddle](paddle); ayrıca diğer sağlayıcılar için [özel entegrasyon](custom-store). ### Ürünler, teklifler ve access level'lar \{#products-offers-and-access-levels\} Adapty, sattığınız şeyi kullanıcıların eriştiği şeyden ayırır. Bu ayrım sayesinde fiyatları değiştirebilir, ürünleri değiştirebilir ya da yeni teklifler başlatabilirsiniz — uygulama güncellemesine gerek kalmaz. Bunu mümkün kılan üç temel bileşen vardır: - **[Ürünler](product)** — tek bir ürün, App Store, Play Store ve web SKU'larınızı (abonelikler, tek seferlik satın almalar veya consumable'lar) bir araya getirir; böylece kataloğu tek bir yerden yönetirsiniz. - **[Teklifler](offers)** — dönüşümü artıran araçlar: başlangıç, promosyon ve geri kazanma indirimleri. - **[Access level'lar](access-level)** — erişim yetkilerini tek tek ürünlerden bağımsız hale getirmenizi sağlar. ### Flow'lar ve placement'lar \{#flows-and-placements\} Gelir getiren ekranları — paywall'lar, onboarding'ler, quizler — kod yazmadan oluşturun. [Flow'lar](adapty-flow-builder), SDK aracılığıyla cihazda render edilir; bu sayede metin, tasarım ve fiyatlandırmayı uygulama güncellemesi beklemeden istediğiniz zaman değiştirebilirsiniz. Bir [şablondan](paywall-builder-templates) ya da boş bir tuvalden başlayın. Her flow'u bir [placement](placements)'a bağlayın, ardından [segment](segments)'lerden oluşturulan farklı [kitleler](audience) için hedefleme yapın. ### Profiller ve segmentler \{#profiles-and-segments\} Herhangi bir aboneye ait tam geçmişi görmek için [profillere](profiles-crm) bakın — her kullanıcının etkinlik zaman çizelgesi, abonelik durumu, geliri ve özel nitelikleri burada saklanır. Kullanıcı tabanınızı herhangi bir niteliğe göre [segmentlere](segments) ayırın; kullanıcıların gördüklerini kişiselleştirin, analizleri filtreleyin ve A/B testlerini kapsamlı biçimde yönetin. [Etkinlik akışı](event-feed) ise her abonelik olayını gerçekleştiği anda yayınlar. ### A/B testleri ve AI Growth Advisor \{#ab-tests-and-ai-growth-advisor\} En iyi dönüşümü sağlayanı bularak geliri artırın: - **[A/B testleri](ab-tests)** — farklı fiyatları, deneme sürelerini ve flow tasarımlarını test edin. - **[AI Growth Advisor](autopilot)** — bir sonraki A/B testinde neyi denemeniz gerektiğini tam olarak söyler. Paywall'ınızı 20.000'den fazla abonelik uygulamasıyla kıyaslar ve deneyleri beklenen gelir artışına göre sıralar. [Nasıl çalıştığını](autopilot-how-it-works) inceleyin. ### Analitik ve Tahminler \{#analytics-and-predictions\} [Analytics](analytics), mağaza, SDK ve attribution verilerini gerçek zamanlı bir gelir kontrol paneline dönüştürür ve App Store ile Google Play'in kendi başına sunduğundan çok daha fazla [onlarca metrik](metric-comparison-table) sunar. [Kohort](analytics-cohorts), [huni](analytics-funnels), [elde tutma](analytics-retention) ve [dönüşüm](analytics-conversion) analizleriyle daha derine inin. [Tahminler](predicted-ltv-and-revenue), her kohortun LTV'sini aylarca önceden tahmin eder ve istatistiksel anlamlılığa ulaşmadan önce [A/B testi kazananlarını](predictions-in-ab-tests) belirler. Zamanlanmış [raporlar](reports) doğrudan gelen kutunuza ulaşır. ### Geliştirici CLI'ı \{#developer-cli\} [Adapty Geliştirici CLI'ı](developer-cli-quickstart), ürünleri, placement'ları ve access level'ları komut satırından yapılandırmanızı sağlar; terminal tercih eden geliştiriciler için kontrol paneline alternatif bir seçenektir. ## Adapty Ads Manager \{#adapty-ads-manager\} [Adapty Ads Manager](adapty-ads-manager), bir Apple Ads platformudur. Yerel Apple Ads konsolunun yerini yapay zeka destekli optimizasyon, gerçek zamanlı gelir attribution'ı ve rekabetçi istihbarat ile alır. Core her kurulumu, denemeyi, aboneliği ve yenilemeyi zaten takip ettiğinden, Ads Manager reklam harcamalarını doğrudan LTV'ye bağlar. MMP gerekmez. Temel özellikler: - **[Kampanyalar ve anahtar kelimeler](ads-manager)** — kampanyaları, reklam gruplarını ve teklifleri Adapty kontrol panelinden oluşturun ve yönetin. - **[AI Agent](ads-manager-ai-agent)** — düz dille tam huni sorguları ve öneriler. - **[Market Intelligence](ads-manager-market-intelligence)** — 50'den fazla ülkede rakip anahtar kelime stratejileri. - **[CPP A/B Testleri](ads-manager-cpp-ab-tests)** — özel ürün sayfalarını birebir karşılaştırın. - **[Otomasyonlar](ads-manager-automations)** — kampanyalarınız kendiliğinden optimize olur. Metrikleriniz belirlenen eşikleri aştığında teklifler, anahtar kelimeler ve arama terimleri otomatik olarak ayarlanır. ## Adapty Attribution \{#adapty-attribution\} [Adapty Attribution](adapty-user-acquisition), uygulama yüklemelerini ve abonelik gelirini bunlara yol açan reklam kampanyalarıyla eşleştirir. Reklam platformu harcamalarını, takip bağlantısı tıklamalarını ve SDK yükleme olaylarını bir araya getirerek ücretli kanallarınız genelinde ROAS, LTV ve kohort görünümleri oluşturur. Harici bir MMP'ye gerek yoktur. Temel özellikler: - **[Reklam platformu entegrasyonları](ua-integrations)** — Meta Ads, TikTok for Business, FunnelFox ve S3/GCS akışları. - **[Takip bağlantıları](ua-tracking-links)** — Adapty'de oluşturulur, kampanyalarınıza eklenir ve ilk açılışta yüklemelerle eşleştirilir. - **[Ertelenmiş derin bağlantılar](ua-deferred-data)** — yeni kullanıcıları, yüklemeden önce tıklamış olsalar bile ilk açılışta uygulama içindeki doğru içeriğe yönlendirir. - **[Attribution verisi](ua-attribution-data)** — özel mantık için uygulamanızda attribution yükünü alın. ## Adapty Mail \{#adapty-mail\} [Adapty Mail](adapty-mail), kullanıcı verilerini yapay zeka destekli e-posta kampanyalarına dönüştürür. Uygulamanızın mağaza listesi, açılış sayfası ve sosyal profillerinden bir [marka profili](mail-brand) oluşturur, ardından dakikalar içinde eksiksiz bir e-posta dizisi üretir. E-postalar doğrulanmış alan adınızdan gönderilir ve her satın alma, onu tetikleyen e-postaya atfedilir. Ayrı bir e-posta platformuna gerek yoktur. Temel özellikler: - **[Kampanyalar](mail-email-campaigns)** — tek seferde oluşturulan çok e-postalı bir dizi. Bir flow'a bağladığınızda göndermeye başlar. - **[Flow'lar](mail-flows)** — bir kampanyayı bir segment ve *hiç satın almadı* veya *ödeme sorunu* gibi bir abonelik-etkinliği tetikleyicisine bağlayarak otomatik gönderim sağlar. - **[Web paywall](mail-checkout)** — her alıcı için ayrı kişiselleştirilmiş ödeme sayfaları; böylece satın almalar e-postaya attribution edilir. - **[Segmentler](mail-segments)** ve **[profiller](mail-profiles)** — dönüşüm yapma olasılığı en yüksek kullanıcılara ulaşın. Satın alma durumu, ülke veya gelire göre bir segment oluşturun; ardından üzerinde bir kampanya veya flow tetikleyin. Veriler Adapty Core'dan gelir; yalnızca e-posta adresi olan tanımlı profiller dahil edilir. ## Adapty'yi mevcut altyapınıza bağlayın \{#connect-adapty-to-your-existing-stack\} [Üçüncü taraf entegrasyonlar](configuration), abonelik [olaylarını](events) ekibinizin halihazırda kullandığı analitik, attribution ve mesajlaşma platformlarına iletir: - **Analytics**: [Amplitude](amplitude), [Mixpanel](mixpanel), [PostHog](posthog), [Firebase / Google Analytics](firebase-and-google-analytics), [AppMetrica](appmetrica), [SplitMetrics Acquire](splitmetrics). - **Attribution**: [AppsFlyer](appsflyer), [Adjust](adjust), [Branch](branch), [Airbridge](airbridge), [Apple Ads](apple-search-ads), [Singular](singular), [Tenjin](tenjin), [Asapty](asapty), [Facebook Ads](facebook-ads). - **Mesajlaşma**: [Braze](braze), [OneSignal](onesignal), [Pushwoosh](pushwoosh), [Slack](slack). - **Webhook ve ETL**: özel [webhook'lar](webhook), [Amazon S3](s3-exports), [Google Cloud Storage](google-cloud-storage). ## Daha geniş ekosistem \{#the-wider-ecosystem\} İki ürün daha Adapty verilerinize bağlanır, ancak temel yaşam döngüsünün dışındaki ihtiyaçlara hizmet eder. ### FunnelFox [FunnelFox](https://funnelfox.com/docs/integrations/subscription-management/adapty), landing sayfaları ve quizler oluşturarak kullanıcıları uygulamanıza yönlendiren bir web-to-app funnel oluşturucusudur. [Ödeme](https://funnelfox.com/docs/billing/integration-billing-funnelfox) motoru, web üzerindeki ödemeleri toplar. Abonelik takibi ve gelir attribution için FunnelFox'u Adapty'ye bağlayın. ### Adapty Finance [Adapty Finance](https://adapty.io/blog/introducing-adapty-finance/), gelecekteki abonelik gelirlerinizi peşin olarak ödeyen bir hizmettir; böylece mağaza ödemelerini beklemenize gerek kalmaz. ## Sonraki adımlar \{#next-steps\} - **[Adapty bana uygun mu?](is-adapty-right-for-me)** — platforma kullanım senaryosu odaklı bir tur. - **[Hızlı başlangıç kılavuzu](quickstart)** — bir mağaza bağlayın, ürün ekleyin ve SDK'yı entegre edin. - **[Adapty'yi yapay zeka ile yönetin](manage-adapty-with-ai)** — Adapty'yi bir yapay zeka kodlama aracıyla kullanmak için tüm giriş noktaları. --- # File: generate-in-app-purchase-key --- --- title: "App Store Connect'te Uygulama İçi Satın Alma Anahtarı Oluşturma" description: "Güvenli işlemler için uygulama içi satın alma anahtarı oluşturun." --- **In-App Purchase Key**, satın almaların gerçekliğini doğrulamak amacıyla App Store Connect içinde oluşturulan özel bir API anahtarıdır. :::note App Store Server API için API anahtarları oluşturabilmek üzere App Store Connect'te Admin veya Account Holder rolüne sahip olmanız gerekir. API Anahtarlarının nasıl oluşturulacağını [Apple Developer Dokümantasyonu](https://developer.apple.com/documentation/appstoreserverapi/creating-api-keys-to-authorize-api-requests)'nda da okuyabilirsiniz. ::: 1. **App Store Connect**'i açın. [**Users and Access** → **Integrations** → **In-App Purchase**](https://appstoreconnect.apple.com/access/integrations/api/subs) bölümüne gidin. 2. Ardından **Active** başlığının yanındaki ekle düğmesine **(+)** tıklayın. <img src="/assets/shared/img/6d737db-generate_in-app_key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Açılan **Generate In-App Purchase Key** penceresinde, ileride başvurmak üzere anahtara bir ad girin. Bu ad Adapty'de kullanılmayacaktır. 4. **Generate** düğmesine tıklayın. **Generate in-App Purchase Key** penceresi kapandıktan sonra oluşturulan anahtarı **Active** listesinde göreceksiniz. <img src="/assets/shared/img/fac066b-download_inapp_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. API anahtarınızı oluşturduktan sonra, anahtarı dosya olarak indirmek için **Download In-App Purchase Key** düğmesine tıklayın. <img src="/assets/shared/img/d59faff-download_in-app_purchase_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Download in-App Purchase Key** penceresinde **Download** düğmesine tıklayın. Dosya bilgisayarınıza kaydedilir. Bu dosyayı güvende tutmak ve ileride Adapty Kontrol Paneli'ne yüklemek için saklamak çok önemlidir. Oluşturulan dosya yalnızca bir kez indirilebileceğinden, yükleyene kadar güvenli bir yerde sakladığınızdan emin olun. **In-App Purchase** bölümünden oluşturulan .p8 anahtarı, [Adapty'nin App Store ile ilk entegrasyonu yapılandırılırken](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file) kullanılacaktır. **Sırada ne var:** - [App Store entegrasyonunu yapılandırın](app-store-connection-configuration) --- # File: app-store-connection-configuration --- --- title: "App Store entegrasyonunu yapılandırma" description: "Sorunsuz abonelik takibi için App Store bağlantınızı yapılandırın." --- <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/VJQbzoTCkqs?si=l7BPX9mIu6GVGZ0Z" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Bu bölümde, iOS uygulamanız için App Store ile Adapty arasındaki bağlantının nasıl kurulacağı anlatılmaktadır. Bu bağlantı, abonelik analizlerini gösterebilmemiz ve satın alımları doğrulayabilmemiz için gereklidir. Entegrasyonu ilk onboarding sırasında veya daha sonra Adapty Kontrol Paneli'ndeki **App Settings** bölümünden tamamlayabilirsiniz. İlk onboarding sırasında mobil uygulamanız ile Adapty entegrasyonunu yapılandırmış olsanız bile bu ayarları daha sonra **App settings** bölümünden değiştirebilirsiniz. :::danger Yapılandırma değişiklikleri, Adapty SDK yüklü mobil uygulamanız yayına girene kadar Sandbox aşamasında güvenle yapılabilir. Yayın sonrasında yapılan değişiklikler uygulamanızdaki satın alma akışını bozabilir. ::: ## Adım 1. Bundle ID ve Apple app ID'yi Girin \{#step-1-provide-bundle-id-and-apple-app-id\} **Bundle ID** ve **Apple app ID** zorunludur. **Bundle ID**, uygulamanızın App Store'daki benzersiz tanımlayıcısıdır ve abonelik işleme gibi temel Adapty işlevlerini etkinleştirir. **Apple app ID** ise **Products** sayfasından [yeni bir ürün oluşturup mağazalara göndermek](create-product#create-product-and-push-to-store) için de gereklidir. :::note **Apple app ID** olmadan, **Products** sayfasındaki **Create a new product and push to stores** seçeneği devre dışı kalır ve kontrol paneli bunun nedenini göstermez. ::: 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Issuer ID ve Key ID'yi girin \{#step-2-provide-issuer-id-and-key-id\} **In-app purchase Issuer ID**, App Store Connect'te **Issuer ID** olarak geçer ve kimlik doğrulama tokenını oluşturan sağlayıcıyı tanımlayan özel bir ID'dir. **In-App Purchase Key ID**, App Store Connect'te **Key ID** olarak geçer ve [App Store Connect'te In-App Purchase Key Oluşturma](generate-in-app-purchase-key) bölümünde oluşturduğunuz kriptografik anahtarla ilişkili benzersiz bir tanımlayıcıdır. 1. **App Store Connect**'i açın. [**Users and Access** → **Integrations** → **In-App Purchase**](https://appstoreconnect.apple.com/access/integrations/api/subs) bölümüne gidin. 2. **Active** listesinde, [App Store Connect'te In-App Purchase Key Oluşturma](generate-in-app-purchase-key) bölümünde oluşturduğunuz anahtarı bulun. <img src="/assets/shared/img/19a2868-issuer_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Issuer ID**'yi kopyalayıp Adapty Kontrol Paneli'ndeki **In-app purchase Issuer ID** alanına yapıştırın. <img src="/assets/shared/img/c2b42e7-issuer_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Key ID**'yi kopyalayıp Adapty Kontrol Paneli'ndeki **In-app purchase Key ID** alanına yapıştırın. ## Adım 3. In-App Purchase Key dosyasını yükleyin \{#step-3-upload-in-app-purchase-key-file\} [App Store Connect'te In-App Purchase Key Oluşturma](generate-in-app-purchase-key) bölümünde indirdiğiniz **In-App Purchase Key** dosyasını <img src="/assets/shared/img/88cdfff-download_inapp_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty Kontrol Paneli'ndeki **Private key (.p8 file)** alanına yükleyin. <img src="/assets/shared/img/253b840-in-app_file_upload.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Deneme süreleri ve özel teklifler için – promosyon tekliflerini ayarlayın \{#step-4-for-trials-and-special-offers--set-up-promotional-offers\} :::important Bu adım, uygulamanızda [deneme süresi veya başka promosyon teklifleri](offers) varsa zorunludur. ::: 1. [Adım 2](#step-2-provide-issuer-id-and-key-id)'de kullandığınız Key ID'yi **App Store promotional offers** bölümündeki **Subscription key ID** alanına kopyalayın. 2. [Adım 3](#step-3-upload-in-app-purchase-key-file)'te kullandığınız **In-App Purchase Key** dosyasını **App Store promotional offers** bölümündeki **Subscription key (.p8 file)** alanına yükleyin. <img src="/assets/shared/img/promo-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. App Store paylaşılan sırrını girin \{#step-5-enter-app-store-shared-secret\} **App Store shared secret**, aynı zamanda App Store Connect Shared Secret olarak da bilinir; uygulama içi satın almalar ve abonelik makbuzu doğrulaması için kullanılan 32 karakterlik onaltılık bir dizedir. 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçip **General** → **App Information** bölümüne gidin. 2. **App-Specific Shared Secret** alt bölümüne kadar aşağı kaydırın. <img src="/assets/shared/img/2bd112a-shared_secret_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::info **App-Specific Shared Secret** alt bölümü görünmüyorsa Account Holder veya Admin rolüne sahip olduğunuzdan emin olun. Admin rolünüz olmasına rağmen bu alt bölümü göremiyorsanız, uygulamanın Account Holder'ından (App Store Connect'te uygulamayı oluşturan kişiden) uygulama için App Store paylaşılan sırrını oluşturmasını isteyin. Bundan sonra alt bölüm Admin'lere de gösterilecektir. ::: 3. **Manage** düğmesine tıklayın. <img src="/assets/shared/img/2d8b4c0-shared_secret_apple_copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Açılan **App-Specific Shared Secret** penceresinde **Shared Secret**'i kopyalayın. Paylaşılan sır görünmüyorsa önce mevcut olan **Manage** veya **Generate** düğmesine tıklayın, ardından **Shared Secret**'i kopyalayın. 5. Kopyaladığınız **Shared Secret**'i Adapty Kontrol Paneli'ndeki **App Store shared secret** alanına yapıştırın. <img src="/assets/shared/img/4f9624d-shared_secret.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Değişiklikleri kaydetmek için Adapty Kontrol Paneli'nde **Save** düğmesine tıklayın. ## Adım 6. App Store Connect API anahtarı ekleyin \{#step-6-add-app-store-connect-api-key\} [Adapty kontrol panelinden App Store'daki ürünlerinizi yönetebilmek](create-product#create-product-and-push-to-store) için bir App Store Connect API anahtarı oluşturun ve Adapty'ye ekleyin: 1. App Store Connect'te [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) bölümüne gidin ve **+** düğmesine tıklayın. <img src="/assets/shared/img/app-store-connect-api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Generate API key** penceresinde anahtar için bir ad girin ve **Admin** erişimi verin. <img src="/assets/shared/img/generate-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Anahtarınızın yanındaki **Download** düğmesine tıklayın. Anahtarı yalnızca bir kez indirebileceğinizi unutmayın. <img src="/assets/shared/img/download-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty kontrol panelinde [**App settings > iOS SDK**](https://app.adapty.io/settings/ios-sdk) bölümüne gidin ve **Connect API key** düğmesine tıklayın. <img src="/assets/shared/img/connect-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Açılan penceredeki alanları doldurun: - **Issuer ID**: [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) bölümünden kopyalayın. **API keys** tablosunun üzerinde yer alır. <img src="/assets/shared/img/issuer-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Key ID**: [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) bölümünden kopyalayın. Anahtarınızın yanında **API keys** tablosunda yer alır. <img src="/assets/shared/img/key-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **API key**: App Store Connect'ten indirdiğiniz API anahtar dosyasını yükleyin. <img src="/assets/shared/img/app-store-connect-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Connect** düğmesine tıklayın. **Sıradaki adım** - [App Store sunucu bildirimlerini etkinleştirme](enable-app-store-server-notifications) --- # File: enable-app-store-server-notifications --- --- title: "App Store sunucu bildirimlerini etkinleştirin" description: "Abonelik etkinliklerini gerçek zamanlı olarak takip etmek için App Store sunucu bildirimlerini etkinleştirin." --- App Store sunucu bildirimlerini ayarlamak, veri doğruluğunu sağlamak açısından kritik öneme sahiptir; bu sayede iade işlemleri ve diğer etkinlikler dahil olmak üzere App Store'dan anlık güncellemeler alabilirsiniz. :::important App Store Server Notifications V2 desteği için Adapty iOS SDK 2.10.0 veya üzeri gereklidir. ::: 1. Adapty Kontrol Paneli'nde **URL for App Store server notification** bağlantısını kopyalayın. <img src="/assets/shared/img/2901185-app_server_notifications.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. [App Store Connect](https://appstoreconnect.apple.com/apps) sayfasını açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne, ardından **App Store Server Notifications** alt bölümüne gidin. 3. Kopyaladığınız **URL for App Store server notification** değerini **Production Server URL** ve **Sandbox Server URL** alanlarına yapıştırın. <img src="/assets/shared/img/86fb3d2-app_server_notifications_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Ham etkinlikleri iletme \{#raw-events-forwarding\} Zaman zaman Apple'dan gelen ham S2S etkinliklerini doğrudan almak isteyebilirsiniz. Adapty kullanırken bunları almaya devam etmek için endpoint'inizi **URL for forwarding raw Apple events** alanına ekleyin; Apple'dan gelen ham etkinlikleri olduğu gibi size ileteceğiz. <img src="/assets/shared/img/e9f4bba-CleanShot_2021-03-16_at_19.30.272x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Sıradaki adım** Adapty SDK'yı şu platformlar için kurun: - [iOS](sdk-installation-ios) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: troubleshoot-app-store-integration --- --- title: "App Store entegrasyonuyla ilgili sorunları giderme" description: "Apple App Store kurulum sorunlarını çözün — bekleyen sözleşmeler, sunucu bildirimi gecikmeleri ve fiyat uyuşmazlıkları." --- Bu makale, App Store entegrasyonuyla ilgili sık karşılaşılan sorunları ele almaktadır. Aşağıdaki her bölümde belirtiler, temel neden ve çözüm yolu açıklanmaktadır. ## Ürünler görünmüyor \{#products-dont-appear\} İki farklı belirti aynı temel nedene işaret eder: - App Store Connect API anahtarı doğru yapılandırılmış, ancak Adapty ürünleri hiç çekemiyor. - Ürünler App Store Connect'te mevcut ama Adapty'de görünmüyor ya da beklenenden az ürün çıkıyor. SDK, satın alma denemelerinde "Product Id not found" hatası veriyor. En yaygın temel neden **imzalanmamış Apple sözleşmeleri** — ücretli sözleşme, vergi formları veya bankacılık formları beklemede ya da imzalanmamış durumda. Sözleşmeler beklemedeyken App Store Connect API, ürünle ilgili endpoint'lerde sessizce 403 döndürür. Adapty'ye herhangi bir hata iletilmez; ürünler sessizce filtrelenir. **App Store Connect → Agreements, Tax, and Banking** bölümüne gidin ve beklemedeki tüm sözleşmeleri imzalayın. Ardından Adapty'nin **App settings → iOS SDK** bölümünde yeniden senkronize edin. ## App Store Sunucu Bildirimleri "Delayed" Olarak Görünüyor \{#app-store-server-notifications-show-delayed\} App Store Connect'te App Store Sunucu Bildirimleri durumu **Delayed** olarak görünebilir. Bu, Apple'ın abonelik olayı bildirimlerini — yenilemeler, iptaller ve ödeme sorunları — gecikmeli gönderdiği anlamına gelir; bu bildirimler kuyruğa alınır ve geç ulaşır. Kurulum istatistikleri bundan etkilenmez. Adapty, kurulumları sunucu tarafı bildirimlerinden değil, uygulamanın ilk açılışından itibaren sayar. Yenileme veya iptal verileri gecikmeli geliyorsa, bunun en olası nedeni Delayed durumudur. Bu durum genellikle Apple birikmiş bildirimleri işledikçe otomatik olarak düzelir. ## Adapty'deki fiyatlar App Store ile eşleşmiyor \{#prices-in-adapty-dont-match-app-store\} Adapty'nin ürün düzenleme sayfasındaki **price** alanı, ürünün nasıl eklendiğine bağlı olarak farklı davranır. Adapty'de bir ürün oluşturup kontrol panelinden mağazaya gönderirseniz, bu fiyat başlangıç mağaza fiyatı olarak kullanılır. Mağazada zaten mevcut olan bir ürün eklerseniz, bu fiyat yalnızca bir yer tutucudur. Adapty'nin analizleri, entegrasyonları ve SDK, gerçek fiyatları App Store'dan çekerek kullanır. App Store'daki fiyat değişiklikleri yer tutucuyu güncellemek için geri senkronize edilmez ve şu an için yer tutucuyu kontrol panelinden düzenleyemezsiniz. ## CSV fiyat dışa aktarımı boş \{#csv-price-export-is-empty\} CSV fiyat dışa aktarımınız yalnızca sütun başlıklarını döndürdüyse, App Store Connect API anahtarınız tam olarak yapılandırılmamış demektir. Bkz. [6. Adım — App Store Connect API anahtarı ekleme](app-store-connection-configuration#step-6-add-app-store-connect-api-key). ## App Store'a yeni ürün gönderilemiyor \{#cant-push-new-products-to-app-store\} Adapty, kontrol panelinde oluşturduğunuz yeni ürünleri App Store Connect'e gönderebilir. App Store entegrasyonunuz tam olarak yapılandırılmamışsa bu seçenek engellenir. İki ayar gereklidir: - **Apple app ID**: [1. Adım — Bundle ID ve Apple app ID'yi girin](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id) bölümünde yapılandırın. - **App Store Connect API anahtarı**: [6. Adım — App Store Connect API anahtarı ekleyin](app-store-connection-configuration#step-6-add-app-store-connect-api-key) bölümünde yapılandırın. --- # File: enabling-of-devepoler-api --- --- title: "Google Play Console'da Geliştirici API'larını Etkinleştirme" description: "Uygulamanızdaki abonelik yönetimini otomatikleştirmek ve kolaylaştırmak için Adapty'nin Geliştirici API'sini etkinleştirin." --- <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/7dN50n5bcLc?si=c2znttIb--4VcrRO" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Mobil uygulamanız Play Store'da yayınlanıyorsa, Adapty ile entegrasyon için Geliştirici API'larını etkinleştirmek şarttır. Bu adım, uygulamanız ile platformumuz arasındaki kesintisiz iletişimi sağlar; otomatik süreçleri ve gerçek zamanlı veri analizini kolaylaştırarak abonelik modelinizi optimize eder. Aşağıdaki API'ların etkinleştirilmesi gerekir: - [Google Play Android Developer API](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com) - [Google Play Developer Reporting API](https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com) - [Cloud Pub/Sub API](https://console.cloud.google.com/marketplace/product/google/pubsub.googleapis.com) Uygulamanız Play Store üzerinden dağıtılmıyorsa bu adımı atlayabilirsiniz. Ancak Play Store üzerinden satış yapıyorsanız bu adımı şimdilik erteleyebilirsiniz; yine de Adapty'nin temel işlevselliği için bu adım kritik öneme sahiptir. Onboarding sürecini tamamladıktan sonra, **App settings** bölümünden uygulama mağazası ayarlarını yapılandırabilirsiniz. Google Play Console'da Geliştirici API'larını etkinleştirmek için şu adımları izleyin: 1. [Google Cloud Console](https://console.cloud.google.com/)'u açın. 2. Google Cloud penceresinin sol üst köşesinde, kullanmak istediğiniz projeyi seçin veya yeni bir tane oluşturun. Servis hesabı anahtar dosyasını Adapty'ye yükleyene kadar aynı Google Cloud projesini kullandığınızdan emin olun. <img src="/assets/shared/img/fd66a11-google_cloud_project.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. [**Google Play Android Developer API**](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com) sayfasını açın. <img src="/assets/shared/img/f754f72-google_play_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Enable** düğmesine tıklayın ve **Enabled** durumunun görünmesini bekleyin. Bu, Google Android Developer API'sinin etkinleştirildiği anlamına gelir. <img src="/assets/shared/img/d47ed14-google_play_api_create_credentials.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. [**Google Play Developer Reporting API**](https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com) sayfasını açın. <img src="/assets/shared/img/966cf73-Google_play_developer_reporting_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Enable** düğmesine tıklayın ve **Enabled** durumunun görünmesini bekleyin. <img src="/assets/shared/img/e776d77-Google_play_developer_reporting_api_enabled.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. [**Cloud Pub/Sub API**](https://console.cloud.google.com/marketplace/product/google/pubsub.googleapis.com) sayfasını açın. <img src="/assets/shared/img/b13f609-enable_Cloud_Pub_Sub_API.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. **Enable** düğmesine tıklayın ve **Enabled** durumunun görünmesini bekleyin. <img src="/assets/shared/img/3f45602-Cloud_Pub_Sub_API_enabled.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Geliştirici API'ları etkinleştirildi. Bunu Google Cloud Console'un [**APIs & Services**](https://console.cloud.google.com/apis/dashboard) sayfasından doğrulayabilirsiniz. Sayfayı aşağı kaydırın ve sayfanın altındaki tablonun 3 API'ın tamamını içerdiğini kontrol edin: - Google Play Android Developer API - Google Play Developer Reporting API - Cloud Pub/Sub API <img src="/assets/shared/img/b81d174-google_enabled_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Sıradaki adım** - [Google Cloud Console'da servis hesabı oluşturma](create-service-account) --- # File: create-service-account --- --- title: "Google Cloud Console'da servis hesabı oluşturma" description: "Adapty'de güvenli API erişimi için servis hesabı oluşturmayı öğrenin." --- Adapty'nin veri erişimini otomatikleştirebilmesi için Google Play Console'da bir servis hesabı gereklidir. 1. Google Cloud Console'un [**IAM & Admin** -> **Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts) bölümünü açın. Doğru projeyi kullandığınızdan emin olun. <img src="/assets/shared/img/17bbf45-google_cloud_create_service_account.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Service accounts** penceresinde **Create service account** düğmesine tıklayın. <img src="/assets/shared/img/b93eec1-service_account_details.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create service account** penceresinin **Service account details** alt bölümünde istediğiniz **Service Account Name**'i girin. Bu hesabın amacını belirtmek için adın içine "Adapty" eklemenizi öneririz. **Service account ID** otomatik olarak oluşturulacaktır. 4. Servis hesabı e-posta adresini kopyalayın ve ileride kullanmak üzere kaydedin. 5. **Create and continue** düğmesine tıklayın. <img src="/assets/shared/img/e69d713-grant_access_to_project.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Grant this service account access to project** alt bölümündeki **Select a role** açılır listesinden **Pub/Sub -> Pub/Sub Admin** seçeneğini seçin. Bu rol, gerçek zamanlı geliştirici bildirimlerini etkinleştirmek için gereklidir. <img src="/assets/shared/img/976299c-service_account_role.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Add another role** düğmesine tıklayın. 8. Yeni açılan **Role** açılır listesinden **Monitoring -> Monitoring Viewer** seçeneğini seçin. Bu rol, bildirim kuyruğunun izlenmesine olanak tanımak için gereklidir. 9. **Continue** düğmesine tıklayın. <img src="/assets/shared/img/ffe8d82-grant_user_access.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 10. Herhangi bir değişiklik yapmadan **Done** düğmesine tıklayın. **Service accounts** penceresi açılacaktır. **Sırada ne var** - [Google Play Console'da servis hesabına izin verme](grant-permissions-to-service-account) --- # File: grant-permissions-to-service-account --- --- title: "Google Play Console'da hizmet hesabına izin ver" description: "Güvenli ve verimli API erişimi için hizmet hesaplarına izin verin." --- Adapty'nin abonelikleri yönetmek ve satın almaları doğrulamak için kullanacağı hizmet hesabına gerekli izinleri verin. 1. Google Play Console'da [**Users and permissions**](https://play.google.com/console/u/0/developers/8970033217728091060/users-and-permissions) sayfasını açın ve **Invite new users** düğmesine tıklayın. <img src="/assets/shared/img/7b0e614-users_and_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Invite user** sayfasında, oluşturduğunuz hizmet kullanıcısının e-posta adresini girin. <img src="/assets/shared/img/3afd002-invite_user.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Account permissions** sekmesine geçin. <img src="/assets/shared/img/4e2717b-account_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Aşağıdaki izinleri seçin: - View app information and download bulk reports (read-only) - View financial data, orders, and cancellation survey responses - Manage orders and subscriptions - Manage store presence 5. **Invite user** düğmesine tıklayın. 6. **Send invite?** penceresinde **Send invite** düğmesine tıklayın. Hizmet hesabı kullanıcı listesinde görünecektir. **Sırada ne var** - [Google Play Console'da hizmet hesabı anahtar dosyasını oluşturun](create-service-account-key-file) --- # File: create-service-account-key-file --- --- title: "Google Play Console'da servis hesabı anahtar dosyası oluşturma" description: "Adapty ile sorunsuz entegrasyon için servis hesabı anahtar dosyası nasıl oluşturulur öğrenin." --- Play Store'daki mobil uygulamanızı Adapty ile bağlamak için Google Play Console'da özel servis hesabı anahtar dosyaları oluşturmanız ve bunları Adapty'ye yüklemeniz gerekir. Bu dosyalar uygulamanızın güvenliğini sağlar ve yetkisiz erişimi engeller. :::warning Yeni servis hesabınızın aktif hale gelmesi genellikle en az 24 saat sürer. Ancak bir [püf nokta](https://stackoverflow.com/a/60691844) var. [Google Play Console](https://play.google.com/apps/publish/)'da servis hesabını oluşturduktan sonra herhangi bir uygulamayı açın ve **Monetize** -> **Products** -> **Subscriptions/In-app products** bölümüne gidin. Herhangi bir ürünün açıklamasını düzenleyip kaydedin. Bu işlem servis hesabını hemen etkinleştirmeli; değişiklikleri daha sonra geri alabilirsiniz. ::: 1. Google Play Console'da [**Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts) bölümünü açın. Doğru projeyi seçtiğinizden emin olun. <img src="/assets/shared/img/c3156cb-action_manage_keys.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Açılan pencerede **Add key** seçeneğine tıklayın ve açılır menüden **Create new key** öğesini seçin. <img src="/assets/shared/img/44b30ee-create_new_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create private key for [Your_project_name]** penceresinde **Create** düğmesine tıklayın. Özel anahtarınız bilgisayarınıza JSON dosyası olarak kaydedilir. Dosyayı, **Private key saved to your computer** penceresinde gösterilen dosya adını kullanarak bulabilirsiniz. <img src="/assets/shared/img/e7b8101-cretae_private_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Create private key for Your_project_name** penceresinde **Create** düğmesine tıklayın. Bu işlem özel anahtarınızı bilgisayarınıza JSON dosyası olarak kaydeder. Gerekirse açılan **Private key saved to your computer** penceresindeki dosya adını kullanarak dosyayı bulabilirsiniz. <img src="/assets/shared/img/187ddc6-Private_key_saved.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu dosyaya [Google Play Store entegrasyonunu yapılandırırken](google-play-store-connection-configuration) ihtiyacınız olacak. :::warning Yeni servis hesabınızın aktif hale gelmesi genellikle en az 24 saat sürer. Ancak bir [püf nokta](https://stackoverflow.com/a/60691844) var. [Google Play Console](https://play.google.com/apps/publish/)'da servis hesabını oluşturduktan sonra herhangi bir uygulamayı açın ve **Monetize** -> **Products** -> **Subscriptions/In-app products** bölümüne gidin. Herhangi bir ürünün açıklamasını düzenleyip kaydedin. Bu işlem servis hesabını hemen etkinleştirmeli; değişiklikleri daha sonra geri alabilirsiniz. ::: **Sıradaki adım** - [Google Play Store entegrasyonunu yapılandırın](google-play-store-connection-configuration) --- # File: google-play-store-connection-configuration --- --- title: "Google Play Store entegrasyonunu yapılandırma" description: "Sorunsuz uygulama içi satın alma işlemleri için Adapty'de Google Play Store bağlantısını yapılandırın." --- Bu bölüm, Google Play üzerinden satılan mobil uygulamanızı Adapty ile entegre etme sürecini açıklamaktadır. Play Store'daki uygulama yapılandırma verilerinizi Adapty Kontrol Paneli'ne girmeniz gerekecek. Bu adım, satın almaları doğrulamak ve Adapty içinde Play Store'dan abonelik güncellemeleri almak için kritik öneme sahiptir. Bu işlemi ilk onboarding sırasında tamamlayabilir ya da daha sonra Adapty Kontrol Paneli'nin **App Settings** bölümünden değişiklik yapabilirsiniz. :::danger Yapılandırma değişikliği, yalnızca Adapty paywall'larını entegre ettiğiniz mobil uygulamanızı yayınlamadan önce kabul edilebilir. Yayın sonrasında yapılan değişiklik entegrasyonu bozar ve paywall'lar mobil uygulamanızda gösterilmeyi durdurur. ::: ## Adım 1. Paket adını girin \{#step-1-provide-package-name\} Paket adı, uygulamanızın Google Play Store'daki benzersiz tanımlayıcısıdır. Bu, abonelik işleme gibi Adapty'nin temel işlevleri için gereklidir. 1. [Google Play Developer Console](https://play.google.com/console/u/0/developers)'u açın. 2. ID'sine ihtiyaç duyduğunuz uygulamayı seçin. **Dashboard** penceresi açılır. <img src="/assets/shared/img/7889edb-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Uygulama adının altındaki ürün ID'sini bulun ve kopyalayın. 4. Adapty üst menüsünden [**App settings**](https://app.adapty.io/settings/android-sdk)'i açın. <img src="/assets/shared/img/b00066c-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **App settings** penceresinin **Android SDK** sekmesine, kopyaladığınız **Package name** değerini yapıştırın. ## Adım 2. Hesap anahtarı dosyasını yükleyin \{#step-2-upload-the-account-key-file\} 1. [Servis hesabı anahtar dosyası oluşturma](create-service-account) adımında oluşturduğunuz JSON formatındaki servis hesabı özel anahtar dosyasını **Service account key file** alanına yükleyin. <img src="/assets/shared/img/20fdba1-service_key_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Değişiklikleri onaylamak için **Save** düğmesine tıklamayı unutmayın. **Sıradaki adım** - [Google Play Console'da Gerçek zamanlı geliştirici bildirimlerini (RTDN) etkinleştirme](enable-real-time-developer-notifications-rtdn) --- # File: enable-real-time-developer-notifications-rtdn --- --- title: "Google Play Console'da Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) Etkinleştirme" description: "Adapty için Google Play Console'da Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) etkinleştirerek kritik olaylar hakkında bilgi sahibi olun ve veri doğruluğunu koruyun. İade ve diğer önemli olaylar için Play Store'dan anında güncelleme almak üzere RTDN'yi nasıl kuracağınızı öğrenin" --- Gerçek zamanlı geliştirici bildirimlerini (RTDN) kurmak, veri doğruluğu açısından kritik öneme sahiptir; bu sayede Play Store'dan iade bilgileri ve diğer olaylar dahil güncellemeleri anında alabilirsiniz. ## Bildirimleri Etkinleştirme \{#enable-notifications\} 1. **Google Cloud Pub/Sub**'ın etkin olduğundan emin olun. [Bu bağlantıyı](https://console.cloud.google.com/flows/enableapi?apiid=pubsub) açın ve uygulama projenizi seçin. **Google Cloud Pub/Sub**'ı henüz etkinleştirmediyseniz burada etkinleştirmeniz gerekir. <img src="/assets/shared/img/pubsub.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Adapty üst menüsünden [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) sayfasına gidin ve **Google Play RTDN topic name** başlığının yanındaki **Enable Pub/Sub API** alanının içeriğini kopyalayın. <img src="/assets/shared/img/a72ff2d-copy_topic.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note **Enable Pub/Sub API** alanının içeriği yanlış bir formattaysa (doğru format `projects/...` ile başlar), yardım için [Enable Pub/Sub API alanındaki yanlış formatı düzeltme](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) bölümüne bakın. ::: 3. [Google Play Console](https://play.google.com/console/)'u açın, uygulamanızı seçin ve **Monetize with Play** -> **Monetization setup** bölümüne gidin. **Google Play Billing** bölümünde **Enable real-time notifications** onay kutusunu işaretleyin. 4. Adapty **App Settings**'de kopyaladığınız **Enable Pub/Sub API** alanının içeriğini **Topic name** alanına yapıştırın. 5. Google Play Console'da **Save changes**'e tıklayın. <img src="/assets/shared/img/e55ba0e-paste_topic_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Bildirimleri Test Etme \{#test-notifications\} Gerçek zamanlı geliştirici bildirimlerine başarıyla abone olup olmadığınızı kontrol etmek için: 1. Google Play Console ayarlarındaki değişiklikleri kaydedin. 2. Google Play Console'daki **Topic name** alanının altında **Send test notification**'a tıklayın. <img src="/assets/shared/img/rtdn-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adapty'de [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) sayfasına gidin. Test bildirimi gönderildiyse, konu adının üzerinde durumunu göreceksiniz. <img src="/assets/shared/img/rtdn-adapty-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Enable Pub/Sub API Alanındaki Yanlış Formatı Düzeltme \{#fixing-incorrect-format-in-enable-pubsub-api-field\} **Enable Pub/Sub API** alanının içeriği yanlış bir formattaysa (doğru format `projects/...` ile başlar), sorunu gidermek için şu adımları izleyin: ### 1. API Etkinleştirme ve İzinleri Doğrulama \{#1-verify-api-enablement-and-permissions\} Gerekli tüm API'lerin etkinleştirildiğinden ve izinlerin servis hesabına doğru şekilde verildiğinden emin olun. Bu adımları daha önce tamamlamış olsanız bile, hiçbir alt adımın atlanmadığından emin olmak için tekrar gözden geçirmeniz önemlidir. Aşağıdaki bölümlerdeki adımları tekrarlayın: 1. [Google Play Console'da Geliştirici API'lerini Etkinleştirme](enabling-of-devepoler-api) 2. [Google Cloud Console'da Servis Hesabı Oluşturma](create-service-account) 3. [Google Play Console'da Servis Hesabına İzin Verme](grant-permissions-to-service-account) 4. [Google Play Console'da Servis Hesabı Anahtar Dosyası Oluşturma](create-service-account-key-file) 5. [Google Play Store Entegrasyonunu Yapılandırma](google-play-store-connection-configuration) ### 2. Alan Politikalarını Düzenleme \{#2-adjust-domain-policies\} **Domain restricted contacts** ve **Domain restricted sharing** politikalarını değiştirin: 1. [Google Cloud Console](https://console.cloud.google.com/)'u açın ve uygulamanızı yönetmek için servis hesabını oluşturduğunuz projeyi seçin. 2. **Quick Access** bölümünde **IAM & Admin**'i seçin. <img src="/assets/shared/img/google-cloud-IAM-and-Admin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Sol panelde **Organization Policies**'i seçin. 4. **Domain restricted contacts** politikasını bulun. <img src="/assets/shared/img/google-cloud-policy-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Actions** sütunundaki üç nokta düğmesine tıklayın ve **Edit policy**'yi seçin. 6. Politika düzenleme penceresinde: 1. **Policy source** altında **Override parent's policy** radyo düğmesini seçin. 2. **Policy enforcement** altında **Replace** radyo düğmesini seçin. 3. **Rules** altında **ADD A RULE** düğmesine tıklayın. <img src="/assets/shared/img/google-cloud-edit-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **New rule** -> **Policy values** altında **Allow All**'u seçin. <img src="/assets/shared/img/google-cloud-allow-all-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **SET POLICY**'ye tıklayın. 7. **Domain restricted sharing** politikası için 4-6. adımları tekrarlayın. Son olarak, **Google Play RTDN topic name** başlığının yanındaki **Enable Pub/Sub API** alanının içeriğini yeniden oluşturun. Alan artık doğru formatta olacaktır. Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) başarıyla etkinleştirdikten sonra güncellenen politikalar için **Policy source**'u **Inherit parent's policy** olarak geri aldığınızdan emin olun. ## Ham Olay Yönlendirme \{#raw-events-forwarding\} Bazen Google'dan ham S2S olaylarını almaya devam etmek isteyebilirsiniz. Adapty kullanırken bunları almaya devam etmek için endpoint'inizi **URL for forwarding raw Google events** alanına eklemeniz yeterlidir; ham olayları Google'dan geldiği gibi ileteceğiz. <img src="/assets/shared/img/e388892-001774-September-22-GhkjOFbT.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- **Sırada ne var** Adapty SDK'yı şu platformlar için kurun: - [Android](sdk-installation-android) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: stripe --- --- title: "Stripe ile ilk entegrasyon" description: "Sorunsuz abonelik ödeme işlemleri için Stripe'ı Adapty ile entegre edin." --- Adapty, [Stripe](https://stripe.com/) üzerinden yapılan web ödemelerini ve abonelikleri takip ederek web2app abonelik akışlarını destekler. Bu entegrasyon, web üzerinden başlatılan satın almaları (Stripe Checkout, barındırılan ödeme sayfaları veya özel web akışları) kapsar ve bunları mobil uygulama erişimiyle ve analitiğiyle senkronize eder. Aşağıdaki senaryolarda işe yarar: - Web'den satın alma yapan ancak daha sonra uygulamayı yükleyip hesabına giriş yapan kullanıcılara ücretli özelliklere otomatik olarak erişim sağlamak - Tüm abonelik analitiğini tek bir Adapty Kontrol Paneli'nde toplamak (kohortlar, tahminler ve diğer analitik araçlarımız dahil) Web üzerinden satın almalar uygulamalar için giderek daha popüler hale gelse de Apple App Store, yalnızca ABD'de dijital ürünler için uygulama içi satın alımlardan farklı bir sisteme izin vermektedir. Diğer ülkelerde web aboneliklerinizi uygulamanız içinde tanıtmadığınızdan emin olun; aksi takdirde uygulamanız reddedilebilir veya yasaklanabilir. Aşağıdaki adımlar, Stripe entegrasyonunun nasıl yapılandırılacağını açıklar. :::important Bu entegrasyon, Stripe web satın almalarının takibine ve senkronizasyonuna odaklanır. Kullanıcıları uygulamadan web ödeme sayfasına yönlendirmeniz gerekiyorsa [Web paywalls](web-paywall) bölümüne bakın. ::: ## 1\. Stripe'ı Adapty'ye bağlama \{#1-connect-stripe-to-adapty\} Bu entegrasyon, esas itibarıyla Adapty'nin webhook aracılığıyla Stripe'tan abonelik verilerini çekmesine dayanır. Bu nedenle, API Anahtarlarını sağlayarak ve Stripe'ta Adapty'nin webhook URL'sini kullanarak Adapty hesabınızı Stripe hesabınıza bağlamanız gerekir. Webhook yapılandırmanızı otomatikleştirmek için Stripe'a Adapty uygulamasını yükleyin: :::note Aşağıdaki adımlar hem Stripe'ın Production hem de Test modları için aynıdır; ancak her biri için farklı API anahtarları kullanmanız gerekecektir. ::: 0. Stripe'ı test modunda mı yoksa canlı modda mı bağlayacağınızı belirleyin. Başlangıçta bunu test modunda yapıyorsanız, aşağıdaki adımları canlı mod için de tekrarlamanız gerekecektir. 1. [Stripe App Marketplace](https://marketplace.stripe.com/apps/adapty)'e gidin ve Adapty uygulamasını yükleyin. Sandbox modunun uygulama yüklemeyi desteklemediğini unutmayın. Bunu yalnızca production veya test modunda yapabilirsiniz. <img src="/assets/shared/img/stripe1.png"/> 2. Uygulamaya gerekli izinleri verin. Bu, Adapty'nin abonelik verilerine ve geçmişine erişmesini sağlayacaktır. Ardından devam etmek için **Continue to app settings** düğmesine tıklayın. İzin açılır penceresinin alt kısmında, uygulamayı canlı modda mı yoksa test modunda mı yükleyeceğinizi seçebilirsiniz. <img src="/assets/shared/img/stripe2.png"/> 3. Açılır pencerede yeni bir kısıtlı anahtar oluşturun. E-postanız, Touch ID veya güvenlik anahtarınızı kullanarak kimliğinizi doğrulamanız gerekecektir. Anahtarı oluşturduktan sonra tekrar göremezsiniz; bu nedenle bir parola yöneticisinde veya güvenli bir depoda saklayın. <img src="/assets/shared/img/stripe4.png"/> 4. Oluşturulan anahtarı açılır pencereden kopyalayın ve Adapty'nin [App Settings → Stripe](https://app.adapty.io/settings/stripe) sayfasına gidin. Anahtarı, modunuza göre **Stripe App Restricted API Key** bölümüne yapıştırın. Test ve canlı modlar için farklı anahtarlar oluşturmanız gerektiğini unutmayın. <img src="/assets/shared/img/Stripe3.png"/> Hepsi bu kadar! Şimdi Stripe'ta ürünlerinizi oluşturun ve bunları Adapty'ye ekleyin. <Details> <summary>Kullanımdan kaldırılan kurulum akışı</summary> 1. Stripe'ta [Developers → API Keys](https://dashboard.stripe.com/apikeys) bölümüne gidin: <img src="/assets/shared/img/6549602-CleanShot_2023-12-06_at_17.29.122x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Secret key** başlığının yanındaki **Reveal live (test) key button** düğmesine tıklayın, ardından kopyalayın ve Adapty'nin [App Settings → Stripe](https://app.adapty.io/settings/stripe) sayfasına gidin. Anahtarı buraya yapıştırın: <img src="/assets/shared/img/2989508-CleanShot_2023-12-07_at_14.59.122x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Ardından Adapty'deki aynı sayfanın alt kısmından Webhook URL'sini kopyalayın. Stripe'ta [**Developers** → **Webhooks**](https://dashboard.stripe.com/webhooks) bölümüne gidin ve **Add endpoint** düğmesine tıklayın: <img src="/assets/shared/img/e7149f5-CleanShot_2023-12-07_at_17.31.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty'den kopyaladığınız webhook URL'sini **Endpoint URL** alanına yapıştırın. Ardından webhook **Version** alanında **Latest API version** seçeneğini seçin. Sonra aşağıdaki olayları seçin: - charge.refunded - customer.subscription.created - customer.subscription.deleted - customer.subscription.paused - customer.subscription.resumed - customer.subscription.updated - invoice.created - invoice.updated - payment_intent.succeeded <img src="/assets/shared/img/cbc5404-CleanShot_2023-12-07_at_17.36.232x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. "Add endpoint" düğmesine basın, ardından "Signing secret" altındaki "Reveal" düğmesine basın. Bu, webhook verilerinin Adapty tarafında çözümlenmesinde kullanılan anahtardır; açıkladıktan sonra kopyalayın: <img src="/assets/shared/img/0460cbb-CleanShot_2023-12-07_at_17.52.582x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Son olarak, bu anahtarı Adapty'nin App Settings → Stripe sayfasındaki "Stripe Webhook Secret" alanına yapıştırın: <img src="/assets/shared/img/055db20-CleanShot_2023-12-07_at_14.56.212x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Details> ## 2\. Stripe'ta ürün oluşturma \{#2-create-products-on-stripe\} :::note Bunu test modunda yapıyorsanız, bu adıma devam etmeden önce Stripe'ın da Test moduna geçtiğinden emin olun. ::: Stripe'ın [Product catalog](https://dashboard.stripe.com/products?active=true) bölümüne gidin ve satmak istediğiniz ürünleri ve fiyatlandırma planlarını oluşturun. Stripe'ın ürün başına birden fazla fiyatlandırma planına izin verdiğini unutmayın; bu, ek ürünler oluşturmaya gerek kalmadan teklifinizi özelleştirmek için kullanışlıdır. <img src="/assets/shared/img/b202e2e-CleanShot_2023-12-06_at_15.06.262x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning Şu anda Adapty yalnızca **Flat rate** (9,99 $/ay) veya **Package pricing** (9,99 $/10 birim) seçeneklerini desteklemektedir; bunlar uygulama mağazalarına benzer şekilde çalışır. **Tiered pricing**, **Usage-based fee** ve **Customer chooses price** seçenekleri desteklenmemektedir. ::: ## 3\. Stripe ürünlerini Adapty'ye ekleme \{#3-add-stripe-products-to-adapty\} :::warning Ürünler zorunludur! Stripe ürünlerinizi Adapty Kontrol Paneli'nde oluşturduğunuzdan emin olun. Adapty yalnızca bu ürünlere bağlı işlemler için olayları takip eder; bu adımı atlamamanız gerekir, aksi takdirde işlem olayları oluşturulmaz. ::: Stripe'a App Store ve Google Play ile aynı şekilde davranıyoruz: dijital ürünlerinizi sattığınız başka bir mağazadır. Yapılandırması da benzer şekildedir: Stripe ürünlerini (`product_id` ve `price_id` değerleriyle birlikte) Adapty'nin Ürünler bölümüne ekleyin: <img src="/assets/shared/img/stripe-add-product.webp" style={{ border: 'none', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Stripe'taki ürün kimlikleri `prod_...`, fiyat kimlikleri ise `price_...` şeklinde görünür. Bunları Stripe'ın [Product Catalog](https://dashboard.stripe.com/products?active=true) bölümünde herhangi bir ürünü açtığınızda kolayca bulabilirsiniz: <img src="/assets/shared/img/14a72d7-CleanShot_2023-12-06_at_17.32.512x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Gerekli tüm ürünleri ekledikten sonra, bir sonraki adım Stripe'a satın almayı kimin yaptığını bildirmektir; böylece Adapty tarafından işlenebilir. ## 4\. Web'den yapılan satın almalara kullanıcı kimliğinizi ekleme \{#4-enrich-purchases-made-on-the-web-with-your-user-id\} Adapty, kullanıcıların access level'larını sağlamak ve güncellemek için tek bilgi kaynağı olarak Stripe'tan gelen webhook'lara dayanır. Ancak bu entegrasyonun düzgün çalışması için kendi tarafınızdan Stripe ile çalışırken ek bilgi sağlamanız gerekir. Access level'ların platformlar arası (web veya mobil) tutarlı olması için Adapty'nin webhook'lardan tanıyabileceği tek bir kullanıcı kimliğine güvenmeniz gerekir. Bu, kullandığınız yetkilendirme sisteminden kullanıcının e-postası, telefon numarası veya herhangi bir başka kimlik olabilir. Kullanıcılarınızı tanımlamak için hangi kimliği kullanmak istediğinize karar verin. Ardından, Stripe üzerinden ödemeyi başlatan kod bölümüne erişin ve bu kullanıcı kimliğini [Stripe Subscription](https://docs.stripe.com/api/subscriptions/object#subscription_object-metadata) (`sub_...`) veya [Checkout Session](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-metadata) nesnesinin (`ses_...`) `metadata` nesnesine `customer_user_id` olarak şu şekilde ekleyin: ```json showLineNumbers title="Stripe Metadata contents" {'customer_user_id': "YOUR_USER_ID"} ``` Bu basit ekleme, kodunuzda yapmanız gereken tek şeydir. Bundan sonra Adapty, Stripe'tan aldığı tüm webhook'ları ayrıştıracak, bu `metadata`'yı çıkaracak ve abonelikleri müşterilerinizle doğru şekilde ilişkilendirecektir. :::warning Kullanıcı kimliği zorunludur Aksi takdirde bu kullanıcıyı eşleştirip mobilden access level sağlamamızın hiçbir yolu yoktur. `metadata`'ya `customer_user_id` sağlamazsanız, Adapty'nin `customer_user_id`'yi başka yerlerde aramasını sağlayabilirsiniz: Stripe'ın Customer nesnesindeki `email` veya Stripe'ın Session nesnesindeki `client_reference_id`. Profil oluşturma davranışını yapılandırma hakkında daha fazla bilgi için [aşağıya bakın](stripe#profile-creation-behavior) ::: :::note Stripe'ta Customer da zorunludur Checkout Sessions kullanıyorsanız, `customer_creation` değerini `always` olarak ayarlayarak [bir Stripe Customer oluşturduğunuzdan emin olun](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer_creation). ::: ## 5\. Mobil kullanıcılara erişim sağlama \{#5-provide-access-to-users-on-the-mobile\} Web'den gelen mobil kullanıcıların ücretli özelliklere erişebilmesini sağlamak için, bir önceki adımda sağladığınız `customer_user_id` ile `Adapty.activate()` veya `Adapty.identify()` fonksiyonunu çağırmanız yeterlidir (daha fazlası için <InlineTooltip tooltip="Kullanıcıları tanımlama">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip> bölümlerine bakın). ## 6\. Entegrasyonunuzu test etme \{#6-test-your-integration\} Yukarıdaki adımları hem Sandbox hem de Production için tamamladığınızdan emin olun. Stripe'ın Test modundan yaptığınız işlemler Adapty'de Sandbox olarak değerlendirilecektir. :::info Hepsi bu kadar! Kullanıcılarınız artık web'de satın alma işlemlerini tamamlayabilir ve uygulamanızdaki ücretli özelliklere erişebilir. Ayrıca tüm abonelik analitiğinizi tek bir yerde görebilirsiniz. ::: ## Profil oluşturma davranışı \{#profile-creation-behavior\} Adapty, bir satın almanın mobilde kullanılabilir olması için onu bir [müşteri profiline](profiles-crm) bağlamak zorundadır; bu nedenle varsayılan olarak Stripe'tan webhook aldığında profil oluşturur. Adapty'de müşteri kullanıcı kimliği olarak ne kullanmak istediğinizi seçebilirsiniz: 1. **Varsayılan ve önerilen:** [Yukarıdaki 4. adımda](stripe#4-enrich-purchases-made-on-the-web-with-your-user-id) metadata'ya eklediğiniz `customer_user_id` 2. Stripe'ın Customer nesnesindeki `email` (bkz. [Stripe'ın dokümantasyonu](https://docs.stripe.com/api/customers/object#customer_object-email)) 3. Stripe'ın Session nesnesindeki `client_reference_id` (bkz. [Stripe'ın dokümantasyonu](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-client_reference_id)) [App Settings → Stripe](https://app.adapty.io/settings/stripe) bölümünden hangi kimliği kullanmak istediğinizi yapılandırabilirsiniz. :::warning **Not:** Stripe'tan gelen belirli bir işlem, belirtilen kimliği içermiyorsa profil oluşturmayız. Bu işlem, bir profil tarafından alınana kadar anonim kalacaktır (örneğin, daha sonra [S2S validate](api-adapty/operations/validateStripePurchase) kullanarak bu işlemi bize manuel olarak bildirirseniz). Analytics'te görünecektir ancak profil sayımına dayanan bölümlerde (LTV, Kohortlar, Dönüşümler vb.) görünmeyecek ve Event feed'de göremeyeceksiniz. ::: Profil oluşturmamak için dördüncü bir seçeneğiniz de var; ancak Analytics'teki yukarıda belirtilen kısıtlamalar nedeniyle bu önerilmez. ## Mevcut kısıtlamalar \{#current-limitations\} ### Yükseltme, düşürme ve proration \{#upgrading-downgrading-and-proration\} Yükseltme veya düşürme gibi abonelik değişiklikleri, orantılı ücretlere (proration) yol açabilir. Adapty bu ücretleri gelir hesaplamalarında dikkate almaz. Bu seçenekleri Stripe kontrol paneli üzerinden manuel olarak devre dışı bırakmanız en iyisi olacaktır. Ayrıca Stripe API üzerinden `proration_behaviour` öznitelik değerini `none` olarak ayarlayarak da devre dışı bırakabilirsiniz. ### İptaller \{#cancellations\} Stripe'ın iki abonelik iptal seçeneği vardır: 1. Anlık iptal: Abonelik, herhangi bir proration seçeneğiyle ya da seçeneği olmaksızın hemen iptal edilir 2. Dönem sonunda iptal: Abonelik, mevcut fatura döneminin sonunda iptal edilir (uygulama mağazalarındaki uygulama içi aboneliklere benzer şekilde). Adapty her iki seçeneği de destekler; ancak anlık iptal için gelir hesaplaması proration seçeneğini göz ardı eder. ### Fatura Sorunları ve Ek Süre \{#billing-issues-and-grace-period\} Müşteri ödemeyle ilgili bir sorunla karşılaştığında, Adapty bir fatura sorunu olayı oluşturur ve erişim iptal edilir. Şu an için Stripe'ın ek süresini (Grace Period) desteklemiyoruz; bu, gelecek sürümlerde eklenecektir. ### Geri ödemeler \{#refunds\} Adapty yalnızca tam geri ödemeleri takip eder. Proration veya kısmi geri ödemeler şu anda desteklenmemektedir. ### İşlem kimliği benzersizliği \{#transaction-id-uniqueness\} Adapty, profilleri ve işlemleri `store_transaction_id` ve `store_original_transaction_id` kullanarak eşleştirir. Bunların Test ve Production ortamları arasında **benzersiz olması gerekir**. #### Bu neden önemlidir \{#why-this-matters\} Aynı işlem kimliği her iki ortamda da mevcutsa Adapty bunları tek bir işlem olarak değerlendirir ve şu sorunlara yol açar: - Production satın almalarının Test access level'larını ve ürün kimliklerini devralması - API yanıtlarında yanlış ürün kimlikleri ve ortamlar - Profil bağlantısının ve abonelik olaylarının bozulması #### Benzersizlik nasıl sağlanır \{#how-to-ensure-uniqueness\} Stripe fatura kimlikleri, Test ve Live ortamları arasında örtüşebilir. Ortamlar arası çakışmaları önlemek için aşağıdaki yaklaşımlardan birini seçin: #### 1. Seçenek: Ortam önekleri ile hesap düzeyinde numaralandırma \{#option-1-account-level-numbering-with-environment-prefixes\} Her ortam için ayrı ayrı önekler yapılandırın: 1. Stripe Dashboard'da Test moduna geçin. 2. [Settings → Billing → Invoices](https://dashboard.stripe.com/settings/account/?support_details=true) bölümüne gidin. 3. **Invoice numbering** değerini **Sequentially across your account** olarak ayarlayın. 4. **Invoice prefix** değerini TEST- (veya test ortamına özgü başka bir önek) olarak ayarlayın. 5. Live moda geçin ve LIVE- (veya canlı ortama özgü başka bir önek) önekini kullanarak 2-4. adımları tekrarlayın. #### 2. Seçenek: Müşteri düzeyinde numaralandırma \{#option-2-customer-level-numbering\} [**Stripe settings** -> **Billing** -> **Invoices** sekmesindeki](https://dashboard.stripe.com/settings/account/?support_details=true) **Invoice numbering** değerini **Sequentially for each customer (customer-level)** olarak ayarlayın. Yukarıdaki yapılandırmayla bile bir faturayı silerseniz Stripe aynı müşterinin yeni faturaları için bu kimliği yeniden kullanabilir. Mümkün olduğunca fatura silmekten kaçınmak en iyisidir. ### Stripe Checkout veya Payment Links aracılığıyla tek seferlik satın almalar \{#one-time-purchases-via-stripe-checkout-or-payment-links\} Adapty, Stripe Checkout (`mode=payment`) veya Payment Links aracılığıyla yapılan tek seferlik (abonelik dışı) satın almaları yalnızca Stripe satın alma için bir fatura oluşturduğunda takip eder. Varsayılan olarak, Stripe tek seferlik Checkout satın almaları için fatura oluşturmaz. Bu durumda `payment_intent.succeeded` fatura verisi olmadan gelir ve bu Adapty'nin işlemi kaydetmesi için yeterli değildir. Tek seferlik Checkout satın almalarını Adapty'de takip etmek için oturumu oluştururken [fatura oluşturmayı etkinleştirin](https://docs.stripe.com/payments/checkout/receipts?payment-ui=stripe-hosted#paid-invoices-hosted). Stripe daha sonra bir fatura oluşturur ve Adapty'nin işlemi kaydetmek için işlediği `invoice.created` ve `invoice.updated` olaylarını gönderir. ## Stripe verilerinizden daha fazla yararlanın \{#get-more-from-your-stripe-data\} Stripe ile entegrasyon sağladıktan sonra Adapty hemen içgörüler sunmaya hazır olur. Stripe verilerinizden en iyi şekilde yararlanmak için, tüm abonelik analitiğinizi tek bir Adapty Kontrol Paneli'nde toplayarak Stripe olaylarını iletmek amacıyla ek Adapty entegrasyonları kurabilirsiniz. :::tip Gelişmiş analitik için, satın almaları belirli paywall örneklerine atfetmek amacıyla Stripe metadata'nıza bir `variation_id` ekleyebilirsiniz. Bu, hangi paywall gösteriminin dönüşüme yol açtığını takip etmek istediğiniz şirket içi web paywalls uygularken özellikle yararlıdır. `variation_id`'nin yalnızca Stripe Subscription (`sub_...`) ve Checkout Session (`ses_...`) nesnelerindeki metadata'dan okunduğunu unutmayın: ```json showLineNumbers title="Stripe Metadata with variation_id" { 'customer_user_id': "YOUR_USER_ID", 'variation_id': "YOUR_VARIATION_ID" } ``` ::: Stripe olaylarınızı iletmek ve analiz etmek için kullanabileceğiniz entegrasyonlar: - [Amplitude](amplitude/) - [Webhook](webhook) - [Firebase](firebase-and-google-analytics) - [Mixpanel](mixpanel) - [Posthog](posthog) ### Desteklenen Stripe olayları \{#supported-stripe-events\} Adapty aşağıdaki Stripe olaylarını destekler: - charge.refunded - customer.subscription.created - customer.subscription.deleted - customer.subscription.paused - customer.subscription.resumed - customer.subscription.updated - invoice.created - invoice.updated - payment_intent.succeeded --- # File: paddle --- --- title: "Paddle ile başlangıç entegrasyonu" description: "Kesintisiz abonelik ödeme işleme için Paddle'ı Adapty ile entegre edin." --- Adapty, [Paddle](https://www.paddle.com/) aracılığıyla yapılan web ödemelerini ve abonelikleri takip ederek web2app abonelik akışlarını destekler. Bu entegrasyon, web üzerinden başlatılan satın almaları kapsar ve bunları uygulama içi satın almalarla birlikte mobil uygulama erişimi ve analitiğiyle senkronize eder. Aşağıdaki senaryolarda işe yarar: - Hem uygulama içi satın almalardan hem de web sitesi satın almalarından gelen abonelik verilerini tek bir sistemde toplayın - Web sitenizden satın alan kullanıcılara mobil uygulamanızdaki ücretli özelliklere erişim verin - Tüm satış kanallarına ait analitik ve abonelik verilerini tek bir kontrol panelinde görüntüleyin :::note Apple artık ABD App Store uygulamalarının harici ödeme sistemlerine bağlantı içermesine izin veriyor; ancak uygulamaların harici seçeneklerin yanı sıra uygulama içi satın alma da sunması gerekebilir. Bulunduğunuz bölge ve uygulama kategorisi için güncel App Store kurallarını kontrol edin. ::: :::note Bu entegrasyon, Paddle web satın alımlarının takibini ve senkronizasyonunu kapsar. Kullanıcıları uygulamadan web ödeme sayfasına yönlendirmeniz gerekiyorsa Adapty [web paywall'larını](web-paywall) kullanın. ::: Paddle entegrasyonunu kurmak için şu adımları izleyin: ## 1\. Paddle'ı Adapty'ye Bağlama \{#1-connect-paddle-to-adapty\} Entegrasyon, Paddle'dan Adapty'ye abonelik verileri göndermek için webhook'lar kullanır. Adapty ve Paddle hesaplarınızı bağlamak için şunları yapmanız gerekir: 1. Paddle API anahtarlarınızı sağlayın. 2. Adapty'nin webhook URL'sini Paddle'a ekleyin. :::note Aşağıdaki adımlar hem Production hem de Test ortamları için geçerlidir. İkisini aynı anda yapılandırabilirsiniz. Verilen bağlantılar Production ortamı içindir; Test ortamı bağlantılarını almak için her URL'nin başına `sandbox-` ekleyin. Örneğin `https://vendors.paddle.com/authentication-v2` yerine `https://sandbox-vendors.paddle.com/authentication-v2` kullanın. ::: ### 1.1. Paddle API Anahtarlarını Alma ve Ekleme \{#11-get-and-add-paddle-api-keys\} 1. Paddle'da [Developer Tools → Authentication](https://vendors.paddle.com/authentication-v2) sayfasına gidin ve **New API key** düğmesine tıklayın. <img src="/assets/shared/img/paddle-new-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Anahtara bir ad verin ve son kullanma tarihini belirleyin. API anahtarının Adapty ile çalışabilmesi için tüm varlıklara **Read** izni vermeniz gerekir. **Save** düğmesine tıklayın. <img src="/assets/shared/img/paddle-key.webp" style={{ border: 'none', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Copy key** düğmesine tıklayın. <img src="/assets/shared/img/copy-paddle-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty'de [App Settings → Paddle](https://app.adapty.io/settings/paddle) sayfasına gidin ve anahtarı **Paddle API key** bölümüne yapıştırın. :::warning Paddle API anahtarınız için bir son kullanma tarihi belirlediyseniz, süresi dolmadan önce yeni bir anahtar oluşturup Adapty'de güncellemeniz gerekir. Anahtar süresi dolduğunda entegrasyon herhangi bir uyarı vermeden çalışmayı durduracak ve kullanıcılar satın alma yapamayacaktır. ::: <img src="/assets/shared/img/paddle-api-keys-adapty.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 1.2. Adapty'ye Gönderilecek Etkinlikleri Ekleme \{#12-add-events-that-will-be-sent-to-adapty\} 1. Adapty'deki **Paddle** sayfasından **Webhook URL**'yi kopyalayın. 2. Paddle'da [**Developer Tools → Notifications**](https://vendors.paddle.com/notifications-v2) sayfasına gidin ve bir webhook eklemek için **New destination** düğmesine tıklayın. <img src="/assets/shared/img/paddle-webhook.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Webhook için açıklayıcı bir ad girin. Gerektiğinde kolayca bulabilmek için "Adapty" ifadesini eklemenizi öneririz. 4. Adapty'deki **Webhook URL**'yi **URL** alanına yapıştırın. Doğru ortam için webhook kullandığınızdan emin olun. 5. **Notification type** olarak **Webhook** seçeneğini belirleyin. <img src="/assets/shared/img/paddle-create-webhook.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Aşağıdaki etkinlikleri seçin: - `subscription.created` - `subscription.updated` - `transaction.created` - `transaction.updated` - `adjustment.created` - `adjustment.updated` <img src="/assets/shared/img/paddle_events.png" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Webhook kurulumunu tamamlamak için **Save destination** düğmesine tıklayın. ### 1.3. Webhook Gizli Anahtarını Alma ve Ekleme \{#13-retrieve-and-add-the-webhook-secret-key\} 1. **Notifications** penceresinde, az önce oluşturduğunuz webhook'un yanındaki üç noktaya tıklayın ve **Edit destination** seçeneğini seçin. 2. **Edit destination** panelinde **Secret key** adında yeni bir alan görünecektir. Kopyalayın. <img src="/assets/shared/img/paddle-webhook-secret-key-copy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adapty'de [App Settings → Paddle](https://app.adapty.io/settings/paddle) sayfasına gidin ve anahtarı **Notification secret key** alanına yapıştırın. Bu anahtar, Adapty'deki webhook verilerini doğrulamak için kullanılır. <img src="/assets/shared/img/paddle-webhook-secret-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 1.4. Paddle Müşterilerini Adapty Profilleriyle Eşleştirme \{#14-match-paddle-customers-with-adapty-profiles\} Adapty'nin her satın almayı uygulamanızda kullanılabilmesi için bir [müşteri profiliyle](profiles-crm) ilişkilendirmesi gerekir. Varsayılan olarak, Adapty Paddle'dan webhook aldığında profiller otomatik olarak oluşturulur. Adapty'de `customer_user_id` olarak hangi değerin kullanılacağını seçebilirsiniz: 1. **Varsayılan ve önerilen:** `custom_data` alanında ilettiğiniz `customer_user_id` (bkz. [Paddle belgeleri](https://developer.paddle.com/build/transactions/custom-data)) 2. Paddle Müşteri nesnesindeki `email` (bkz. [Paddle belgeleri](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters)) 3. `ctm-...` formatındaki Paddle Müşteri Kimliği (bkz. [Paddle belgeleri](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters)) 4. Profil oluşturma. Müşteri profilleriniz üzerinde daha fazla kontrol sahibi olmak ve bunu kendiniz yönetmek istiyorsanız bu seçeneği tercih edin. Hangi değerin kullanılacağını [App Settings → Paddle](https://app.adapty.io/settings/paddle) sayfasındaki **Profile creation behavior** alanından yapılandırabilirsiniz. <img src="/assets/shared/img/paddle-users.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 2. Paddle Ürünlerini Adapty'ye Ekleme \{#2-add-paddle-products-to-adapty\} :::warning Paddle ürünlerinizi Adapty Kontrol Paneli'ne eklediğinizden ya da mevcut ürünlerinize bir Paddle ürün kimliği eklediğinizden emin olun. Adapty yalnızca bu ürünlere bağlı işlemlere ait etkinlikleri takip eder. Bu adımı atlarsanız işlem etkinlikleri oluşturulmaz. ::: Paddle, Adapty'de App Store ve Google Play gibi çalışır; dijital ürünlerinizi sattığınız başka bir platformdur. Yapılandırmak için Adapty'deki [Products](https://app.adapty.io/products) bölümüne Paddle'dan ilgili `product_id` ve `price_id` değerlerini ekleyin. <img src="/assets/shared/img/paddle-create-product.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Paddle'da ürün kimlikleri `pro_...`, fiyat kimlikleri ise `pri_...` şeklinde görünür. Bunları [Paddle ürün kataloğunuzda](https://vendors.paddle.com/products-v2) ilgili ürünü açtığınızda bulabilirsiniz: <img src="/assets/shared/img/paddle-product-price.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ürünlerinizi ekledikten sonra bir sonraki adım, Adapty'nin satın almayı doğru kullanıcıyla ilişkilendirebilmesini sağlamaktır. ## 3\. Mobil Uygulamada Kullanıcılara Erişim Sağlama \{#3-provide-access-to-users-on-the-mobile\} Web üzerinden satın alan kullanıcıların mobil uygulamada da erişim kazanmasını sağlamak için `Adapty.activate()` veya `Adapty.identify()` çağrısını, satın alma sırasında ilettiğiniz `customer_user_id` ile yapın. Ayrıntılar için [Kullanıcıları Tanımlama](identifying-users) bölümüne bakın. ## 4\. Entegrasyonu Test Etme \{#4-test-your-integration\} Her şeyi ayarladıktan sonra entegrasyonunuzu test edebilirsiniz. Paddle'ın Test ortamında yapılan işlemler Adapty'de **Test** olarak görünür. Production ortamındaki işlemler ise **Production** olarak görünür. Entegrasyonunuz artık tamamdır. Kullanıcılar web sitenizden abonelik satın alabilir ve mobil uygulamanızda premium özelliklere otomatik olarak erişebilir; siz de tüm abonelik analitiğini tek bir Adapty Kontrol Paneli'nden takip edebilirsiniz. ## Önemli Noktalar \{#important-considerations\} - Adapty'nin analitiğinde işlem tutarlarına vergiler ve Paddle ücretleri dahildir; bu durum, tutarların vergiler ve ücretler sonrası gösterildiği Paddle'ın kontrol panelinden farklıdır. Yani Adapty'de gördüğünüz rakamlar Paddle'dakinden daha yüksek olacaktır. - Diğer mağazalardan farklı olarak, Paddle'daki iade işlemleri yalnızca iade edilen ilgili işlemi etkiler ve aboneliği otomatik olarak iptal etmez. Abonelik, açıkça iptal edilmediği sürece aktif kalmaya devam eder. - Satın almaları belirli paywall örneklerine atfetmek için `custom_data` alanına `variation_id` de ekleyebilirsiniz. Adapty bu veriyi webhook'lardan işleyerek analitiğe dahil eder. ### Ücretli Denemeler \{#paid-trials\} Paddle'da ücretli denemelerle çalışırken Adapty'de iki ürün oluşturmanız gerekir: 1. Bir consumable ürün oluşturun ve bunu deneme süresini ücretlendiren Paddle fiyatıyla ilişkilendirin. 2. Ardından bir abonelik ürünü (Aylık/Haftalık/vb.) oluşturun ve bunu ücretsiz deneme bileşeni içeren Paddle fiyatıyla ilişkilendirin. Paddle'ın bakış açısından bu, tek bir işlemde iki fiyatı olan bir üründür: biri deneme ücreti için (ör. $0,99), diğeri ücretsiz deneme için ($0,00). Adapty açısından ise bu iki ayrı etkinlik oluşturur: deneme ödemesi için abonelik dışı bir satın alma ve abonelik ürünü için bir deneme başlangıcı etkinliği. Örneğin, bir kullanıcı aylık 9,99 $ değerinde bir abonelik için 0,99 $'lık ücretli deneme başlattığında, Paddle her iki fiyatı da içeren tek bir işlem oluşturur. Adapty ise bunu 0,99 $'lık abonelik dışı satın alma (anlık ödeme) ve 0,00 $'lık deneme başlangıcı etkinliği (gelecekte aylık 9,99 $) olarak işler. :::note Kullanıcılar ücretli bir denemeyi iptal ettiğinde **Trial expired** ve **Trial renewal canceled** etkinliklerini alırsınız. ::: ## Paddle verilerinizden daha fazla yararlanın \{#get-more-from-your-paddle-data\} :::important Paddle etkinliklerinizin entegrasyonlarla çalışabilmesi için kullanıcılarınızın uygulamaya en az bir kez App Store/Google Play hesaplarıyla giriş yapmış olması gerekir. ::: Paddle entegrasyonunu tamamladıktan sonra Adapty, hemen içgörüler sunmaya hazır hale gelir. Paddle verilerinizden en iyi şekilde yararlanmak için ek Adapty entegrasyonları kurarak Paddle etkinliklerini iletebilir; böylece tüm abonelik analizlerinizi tek bir Adapty Kontrol Paneli'nde toplayabilirsiniz. Paddle etkinliklerinizi iletmek ve analiz etmek için kullanabileceğiniz entegrasyonlar: - [AppsFlyer](appsflyer) - [Webhook](webhook) - [Posthog](posthog) ## Mevcut sınırlamalar \{#current-limitations\} - **İptal işlemleri**: Paddle'ın iki abonelik iptal seçeneği vardır: 1. Anında iptal: Abonelik hemen iptal edilir. 2. Dönem sonunda iptal: Abonelik, mevcut fatura döneminin sonunda iptal edilir (uygulama mağazalarındaki uygulama içi aboneliklerine benzer şekilde). - **İadeler**: Adapty, tam ve kısmi iadeleri takip eder. - **Ek süre**: Paddle, varsayılan olarak ödeme sorunları için sabit 30 günlük bir ek süre uygular; bu süre boyunca abonelik aktif kalır. [Ek sürenin uzunluğunu ve süre sonundaki eylemi (aboneliği duraklatma veya iptal etme) özelleştirebilirsiniz](https://developer.paddle.com/build/retain/configure-payment-recovery-dunning#prerequisites). **Denemeler**: Deneme süresi sona erdikten sonra ödeme tahsilinde başarısızlık olursa abonelik durumu `past_due` olarak değişir. Production ortamında Paddle'ın Retain özelliği, abonelik iptal edilmeden veya duraklatılmadan önce ödemeyi kurtarmaya çalışmak için bir dunning penceresi uygular. Sandbox ortamında ise Retain kullanılamaz, bu nedenle ödeme yeniden denemesi yapılmaz ve abonelik süresiz olarak `past_due` durumunda kalır. --- **Ayrıca bakın:** - [Paddle'da satın almayı doğrulama, access level edinme ve sunucu taraflı API ile Paddle'dan işlem geçmişini içe aktarma](api-adapty/operations/validatePaddlePurchase) --- # File: custom-store --- --- title: "Diğer mağazalarla ilk entegrasyon" description: "App Store ile Adapty İlk Entegrasyonu: Hızlı Bir Kılavuz" --- Adapty'e hoş geldiniz! Önceliğimiz, uygulamanız için mümkün olan en iyi sonuçları elde etmenize yardımcı olmak. İlk entegrasyon yalnızca [App Store](initial_ios), [Google Play](initial-android), [Stripe](stripe) ve [Paddle](paddle) için gereklidir; çünkü Adapty uygulama, ürün ve tekliflerinizi bu mağazalarla doğrular. Adapty, diğer uygulama mağazalarıyla veri doğrulaması yapmaz ve bu mağazalar üzerinden gerçekleştirilen satın almaları işlemez. Bununla birlikte, diğer mağazalar üzerinden satılan ürünleri Adapty'de işaretleyerek başarılı bir satın almanın ardından ücretli içeriğe erişim sağlayabilir, işlemleri analizlerinize yansıtabilir ve entegrasyonlar aracılığıyla paylaşabilirsiniz. <img src="/assets/shared/img/Adapty-Communication-Scheme.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::important Backend'inizin satın almayı işlediğinden ve işlemi [Adapty sunucu taraflı API](getting-started-with-server-side-api) aracılığıyla Adapty'e gönderdiğinden emin olun. Adapty, işlem alındıktan sonra erişim sağlar, işlem olayı tetikler, entegrasyonlara gönderir ve analizlere yansıtır. ::: Bir ürünü özel bir uygulama mağazası üzerinden satılıyor olarak işaretlemek için ürün oluştururken ilgili uygulama mağazasını seçin. İhtiyacınız olan mağaza listede yoksa, nasıl oluşturulacağı aşağıda açıklanmıştır: 1. **Products** sayfasında, özel bir uygulama mağazası üzerinden satmak istediğiniz ürünü açın. 2. Satış yapmak istediğiniz uygulama mağazasını seçin. Listede yoksa **Create Custom Store** düğmesine tıklayın. <img src="/assets/shared/img/create_custom-appstore.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Mağazanın **Title** ve **Store ID** bilgilerini girin. 4. **Create store** düğmesine tıklayın. Backend'iniz doğru şekilde yapılandırılmışsa Adapty, bu özel mağazadan gelen ürün işlemlerini alır, analizlere, [**Event Feed**](event-feed) sayfasına ve [entegrasyonlara](https://app.adapty.io/integrations) yansıtır ve erişimi buna göre sağlar. ## Özel mağaza verilerinizden daha fazlasını elde edin \{#get-more-from-your-custom-store-data\} :::important Özel mağaza olaylarınızın entegrasyonlarla çalışabilmesi için kullanıcılarınızın uygulamada en az bir kez App Store/Google Play hesaplarıyla oturum açmış olması gerekir. ::: Özel mağaza entegrasyonunuzu kurduktan sonra Adapty hemen içgörüler sunmaya hazırdır. Verilerinizden en iyi şekilde yararlanmak için ek Adapty entegrasyonları kurarak özel mağaza olaylarını iletebilir ve tüm abonelik analizlerinizi tek bir Adapty Kontrol Paneli'nde toplayabilirsiniz. Özel mağaza olaylarınızı iletmek ve analiz etmek için kullanabileceğiniz entegrasyonlar: - [AppsFlyer](appsflyer) - [Webhook](webhook) - [Posthog](posthog) --- # File: transfer-apps --- --- title: "Uygulamanı farklı bir hesaba aktar" description: "Adapty'de uygulama sahibini değiştir" --- Şirketiniz satın alındığında, uygulamanızı satarken veya iş yapılanmanızı yeniden düzenlerken uygulamanızı farklı bir sahibine aktarabilirsiniz. Aktarım süreci; kesintisiz hizmet sağlamak için Adapty, App Store Connect ve Google Play Console'da yapılacak değişikliklerin koordineli şekilde yürütülmesini gerektirir. ## Uygulama sahipliğini aktar \{#transfer-app-ownership\} Önce mağaza transferini tamamlayın, ardından Adapty'de uygulamayı aktarın. Bu sıralama, geçiş sürecinde satın alımların kesintisiz çalışmasını sağlar. :::note Aktarım süreci boyunca ürünleri silmeyin veya yeniden oluşturmayın. Transfer başarıyla tamamlandığını doğrulayana kadar ürün ID'lerini değiştirmeyin. ::: ### App Store (iOS) transferi \{#app-store-ios-transfer\} :::important App Store Connect API anahtarları (Issuer ID, Key ID, .p8 dosyası) uygulama kapsamlı değil, hesap kapsamlıdır. Transfer sonrasında yeni sahibin hesabından yeni API anahtarları oluşturmanız ve bunları Adapty'de güncellemeniz gerekir. Uygulamaya özel paylaşılan gizli anahtar, transfer süreci boyunca makbuzları doğrulamaya devam eder; ancak yeni sahip, transfer tamamlandıktan sonra bunu yeniden oluşturmalı ve Adapty'de güncellemelidir. ::: 1. **Yeni sahip:** Hesabınız yoksa [app.adapty.io](https://app.adapty.io) adresinden bir Adapty hesabı oluşturun. 2. **Eski sahip:** Apple'ın [transfer kılavuzunu](https://developer.apple.com/help/app-store-connect/transfer-an-app/overview-of-app-transfer) takip ederek App Store Connect'te uygulama transferini başlatın. 3. **Yeni sahip:** App Store Connect'teki transferi kabul edin. 4. **Eski sahip:** Adapty'de uygulamayı aktarmak için [support@adapty.io](mailto:support@adapty.io) adresine e-posta gönderin. Uygulama adını ve yeni sahibin e-posta adresini belirtin. 5. **Yeni sahip:** Uygulamayı Adapty'de aldıktan sonra, tüm kimlik bilgilerini kendi hesabınız altında oluşturup yapılandırmak için [App Store entegrasyon kılavuzunu](initial_ios) tamamlayın. ### Google Play (Android) transferi \{#google-play-android-transfer\} 1. **Yeni sahip:** Hesabınız yoksa [app.adapty.io](https://app.adapty.io) adresinden bir Adapty hesabı oluşturun. 2. **Her iki sahip:** Her iki Google Play Developer hesabının da tam olarak kayıtlı olduğundan emin olun. 3. **Eski sahip:** Google Play Console veya Google Play Developer Support üzerinden transfer talebi gönderin. Google; DUNS numaraları, sözleşmeler veya satış kanıtı gibi ek belgeler isteyebilir. 4. **Yeni sahip:** Transfer talebini inceleyin ve onaylayın. 5. **Google:** Google destek ekibi transferi işleme alır; bu süreç genellikle birkaç iş günü sürer, ancak hesap doğrulama, abonelik karmaşıklığı ve ödeme kurulumuna bağlı olarak daha uzun sürebilir. 6. **Eski sahip:** Google transferi tamamladıktan sonra, Adapty'de uygulamayı aktarmak için [support@adapty.io](mailto:support@adapty.io) adresine e-posta gönderin. Uygulama adını ve yeni sahibin e-posta adresini belirtin. 7. **Yeni sahip:** Uygulamayı Adapty'de aldıktan sonra, tüm kimlik bilgilerini kendi hesabınız altında oluşturup yapılandırmak için [Google Play entegrasyon kılavuzunu](initial-android) tamamlayın. Transfer; kullanıcıları, abonelikleri, istatistikleri, derecelendirmeleri ve mağaza listesini kapsar. Mevcut aboneler için faturalandırma sürekliliği korunur; ancak ödemeler, transfer tamamlandıktan sonra yalnızca yeni sahibin satıcı hesabına geçer. Transferden önceki ödeme raporları ve siparişler orijinal hesapta kalır. Ayrıntılı gereksinimler için Google'ın [transfer kılavuzunu](https://support.google.com/googleplay/android-developer/answer/6230247) inceleyin. ## Risk azaltma ve zamanlama \{#risk-mitigation-and-timing\} **Transfer süresince çalışmaya devam edenler:** - Satın almalar ve yenilemeler (uygulamaya özel paylaşılan gizli anahtar, transfer penceresi boyunca makbuzları doğrulamaya devam eder) - Mevcut abonelerin erişimi - SDK çalışmaya devam eder **Geçici olarak duranlar:** - App Store Connect API çağrıları (yeni anahtarlar yapılandırılana kadar) - Sunucu bildirimleri (uç nokta yeniden yapılandırılana kadar) - Kimlik bilgisi geçişi sırasında analizlerde boşluklar oluşabilir **Önerilen zamanlama:** - Transferleri düşük trafikli dönemlerde tamamlayın (birincil kullanıcı saat diliminizde sabah 03:00–06:00 arası) - Yeni sahibin, mağaza transferini kabul ettikten hemen sonra kimlik bilgilerini yapılandırmaya hazır olmasını sağlayın - Transferi kabul etmekle Adapty entegrasyonunu tamamlamak arasında 15-30 dakika süre ayırın **Transfer tamamlandıktan sonra:** - Makbuz doğrulamasını hemen test edin - 48 saat boyunca otomatik yenileme başarı oranlarını izleyin - Sunucu bildirimlerinin sistemlerinize ulaştığını doğrulayın - Yeni satın alımların doğru şekilde takip edildiğini kontrol edin ## Transferin başarıyla tamamlandığını doğrula \{#verify-transfer-completed-successfully\} Hem Adapty hem de mağaza transferlerini tamamladıktan sonra: 1. **Kontrol paneli erişimini kontrol edin**: Yeni sahip, uygulamayı Adapty Kontrol Paneli'nde görebilmelidir. 2. **API anahtarı bağlantısını doğrulayın**: Yeni App Store Connect API Anahtarı veya Google Play hizmet hesabının Adapty'de başarıyla bağlandığını kontrol edin. 3. **SDK bağlantısını test edin**: Uygulamanızı çalıştırın ve Adapty SDK'nın hatasız başlatıldığını doğrulayın. --- # File: installation-of-adapty-sdks --- --- title: "Adapty SDK Kurulumu" description: "iOS, Android ve cross-platform uygulamalar için Adapty SDK'larını kurun." --- Tercihlerinize göre başlamak için üç yol var: - **Platforma özel hızlı başlangıç kılavuzlarını takip edin**: Kılavuzlar üretime hazır kod parçacıkları içerdiğinden uygulama fazla zaman almaz. - [iOS](ios-sdk-overview) - [Android](android-sdk-overview) - [React Native](react-native-sdk-overview) - [Flutter](flutter-sdk-overview) - [Unity](unity-sdk-overview) - [Kotlin Multiplatform](kmp-sdk-overview) - [Capacitor](capacitor-sdk-overview) - **LLM kullanın**: Dokümanlarımız LLM dostu. Adapty dokümantasyonuyla LLM'lerden en iyi şekilde yararlanmak için [kılavuzumuzu](adapty-cursor) okuyun. - **Örnek uygulamaları inceleyin**: - [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) - [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) - [React Native (Saf RN üzerinde temel örnek)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample) - [React Native (Gelişmiş örnek – daha karmaşık durumlarla çalışmanıza olanak tanıdığı için geliştirme sürecinde kullanışlıdır)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools) - [React Native (Expo dev build)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) - [React Native (Expo Go & Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) - [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) - [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets) - [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) - [Capacitor](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples) --- # File: sample-apps --- --- title: "Örnek uygulamalar" description: "" --- Adapty SDK ile hızlıca başlamanıza yardımcı olmak için, temel özelliklerin nasıl entegre edileceğini ve kullanılacağını gösteren örnek uygulamalar hazırladık. Bu uygulamalar; paywall'lar, satın almalar ve analitik takibi için kullanıma hazır implementasyonlar sunuyor. <img src="/assets/shared/img/adapty-scheme.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Örnek uygulamaları neden kullanmalısınız? \{#why-use-sample-apps\} - **Hızlı Entegrasyon:** Adapty SDK'nın gerçek bir uygulamada nasıl çalıştığını görün. - **En İyi Pratikler:** Önerilen implementasyon kalıplarını takip edin. - **Hata Ayıklama ve Test:** Adapty'yi kendi projenize entegre etmeden önce sorunları gidermek ve denemeler yapmak için örnek uygulamaları kullanın. ## Mevcut örnek uygulamalar \{#available-sample-apps\} - [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) - [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) - [React Native (Saf RN ile temel örnek)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample) - [React Native (Gelişmiş örnek – daha karmaşık senaryolarla çalışmanıza olanak tanıdığı için geliştirme sürecinde kullanışlıdır)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools) - [React Native (Expo dev build)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) - [React Native (Expo Go ve Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) - [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) - [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets) - [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) - [Capacitor (React)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-react-example) - [Capacitor (Vue.js)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-vue-example) - [Capacitor (Angular)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-angular-example) - [Capacitor (Gelişmiş geliştirme araçları)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools) --- # File: paywall-builder-templates --- --- title: "Flow oluşturma" description: "Özel tasarlanmış bir galeri şablonundan veya minimal bir başlangıç noktasından yeni bir flow oluşturun." --- Bir flow'u şablondan veya sıfırdan oluşturabilirsiniz. :::link Flow oluşturma hakkında daha fazla bilgi edinmek ister misiniz? [YouTube oynatma listemizde](https://www.youtube.com/playlist?list=PLMksWqaZiWtM) adım adım video eğitimlerini izleyin. ::: ## Flow oluşturma \{#create-flow\} 1. **Flows** sayfasını açın. 2. **Create flow** düğmesine tıklayın. 3. Bir seçenek belirleyin: - **Browse templates** (Şablon kütüphanesini açar) - **Start from scratch** (Boş bir flow oluşturur) 4. Flow adını düzenleyicide yeniden adlandırın. Başlık çubuğundaki flow adına tıklayın ve yeni bir isim girin. :::warning Adapty, aynı isimde birden fazla flow oluşturmanıza izin verir. Her yeni flow'a farklı bir isim verin, aksi hâlde birbirinden ayırt etmesi zor olan çok sayıda **Untitled** flow oluşturursunuz. ::: ### Şablon kullanma \{#use-a-template\} Şablon kütüphanesi, flow'unuz için başlangıç noktası görevi gören birkaç şablon içerir. Her biri, birden fazla ekran, etkileşimli öğe ve çalışan navigasyona sahip eksiksiz bir flow'dur. Özelleştirmek için herhangi bir öğeyi düzenleyebilirsiniz. Şablon uygulamak için: 1. Şablon kütüphanesinde şablon kartlarına göz atın. Her kartta bir flow'dan önizleme ekran görüntüleri gösterilir. 2. İstediğiniz kartın üzerindeki **Use as template** seçeneğine tıklayın. Şablon, builder'da yüklenir. Buradan herhangi bir öğeyi, ekranı veya özelliği değiştirebilirsiniz. ### Sıfırdan başla \{#start-from-scratch\} Sıfırdan başla seçeneği, tek bir boş ekranla bir flow oluşturur. Ekranı [öğe kütüphanesindeki](builder-elements) öğelerle tasarlayabilirsiniz. ## Şablonu değiştirin \{#change-the-template\} Şablonu builder içinden değiştirebilirsiniz. Screens panelini açın ve Şablon kitaplığını yeniden açmak için **Templates** Templates düğmesine tıklayın, ardından yeni bir şablon seçin. :::warning Yeni bir şablon uygulamak mevcut flow taslağınızın üzerine yazar. Adapty onay ister — devam etmek için **Use template**'e, taslağınızı korumak için **Cancel**'a tıklayın. Onaylandıktan sonra önceki taslak geri yüklenemez. Yayınlanmış flow yayında kalmaya devam eder ve etkilenmez. ::: ## Şablonlarda özel fontlar \{#custom-fonts-in-templates\} :::link Ana makale: [Flow Builder'da özel fontlar](using-custom-fonts-in-flow-builder) ::: **Custom font** etiketiyle işaretlenmiş şablonlar özel fontlar kullanır. Bu fontlar mobil SDK ile birlikte gelmez. Şablonun hangi fontları kullandığını görmek için etiketin üzerine gelin. Cihazda istenen tipografiyi görmek için font dosyalarını uygulama paketinize ekleyin. Fontu içermeyen eski uygulama sürümleri sistem fontuna geri döner. Daha eski sürümleri etkilemeden bir yazı tipini değiştirmek için flow'u kopyalayın, kopyada yazı tipini değiştirin ve kopyayı [yazı tipini içeren uygulama sürümlerindeki kullanıcılarla](segments) sınırlandırın. --- # File: builder-ui --- --- title: "Flow Builder Arayüzü" description: "Flow Builder arayüzüne ve çalışma alanına genel bakış." --- Ana Flow Builder arayüzü; görsel öğeler eklemek, özelliklerini düzenlemek ve kullanıcı flow'unun mantığını değiştirmek için gereken tüm araçları içerir. Bu makale, arayüzün her alanını kapsar: ne işe yaradığı ve nerede bulunduğu. :::link Flow oluşturma hakkında daha fazla bilgi edinmek ister misiniz? [YouTube oynatma listemizde](https://www.youtube.com/playlist?list=PLMksWqaZiWtM) adım adım video eğitimlerini izleyin. ::: ## Proje kontrolleri ve faydalı kısayollar (üst araç çubuğu) \{#project-controls-and-useful-shortcuts-top-toolbar\} * **Kapat** Close: Flow düzenleyicisinden çıkıp flows sayfasına dönün. * **Uygulama adı** App: Flow'un hangi uygulamaya ait olduğunu gösterir. * **Tüm flow'lar** Flows: Bu uygulamaya ait tüm flow'ların listesini açın. * **Flow durumu**: Flow adının solundaki simge, mevcut [flow durumunu](builder-save-publish#flow-status) gösterir: - **Taslak** Draft - **Yayımlanıyor** (dönen yükleyici) - **Başarısız** Failed - ya da **Canlı** Live. * **Flow'u yeniden adlandırma**: Yeniden adlandırmak için flow adına tıklayın. Birden fazla flow aynı ada sahip olabilir; bu nedenle [her yeni flow'a benzersiz bir ad verin](paywall-builder-templates#create-flow). * **Görünüm modu geçişi**: Tasarım görünümü Cursor ile [remote config görünümü](customize-flow-with-remote-config) Remote Config arasında geçiş yapın. * **Geri Al/Yeniden Yap**: Flow değişikliklerini geri almak Undo veya yeniden yapmak Redo için ok simgelerine tıklayın. Geri almak için ⌘Z / Ctrl+Z kısayolunu da kullanabilirsiniz. * **Taslağı kaydet / Yayımla**: İlerlemenizi canlıya almadan kaydetmek için **Save draft** düğmesine tıklayın (⌘ / Ctrl+S). [**Publish**](builder-save-publish) düğmesine erişmek için açılır menüyü Open dropdown açın. Flow'unuzu bir [placement'a](create-placement) yalnızca yayımlandıktan sonra ekleyebilirsiniz. ## Önizleme alanı (merkez) \{#preview-area-center\} Çalışma alanının merkezi, flow'unuzun mobil cihazda nasıl görüneceğini simüle eder. * Bir öğeyi seçmek ve özelliklerini düzenlemek için üzerine tıklayın. Bir kapsayıcının içindeki alt öğeyi seçmek için önce kapsayıcıya, ardından alt öğeye tıklayın. * Ekranın kendine ait özellikleri düzenlemek için herhangi bir öğenin dışına tıklayın ya da Screens and Layers panelinden ekranı seçin. * Bir öğenin sırasını değiştirmek için Screens and Layers panelinde o öğenin girişini yukarı veya aşağı sürükleyin. :::warning Flow editörü, duyarlı düzenler oluşturmak için tasarlanmıştır. Bu nedenle öğelerin konumlarını **manuel olarak değiştiremezsiniz** — yalnızca sıralarını değiştirebilirsiniz. Her container'ın düzen ayarları, içindeki öğelerin nasıl dağıtılacağını belirler. ::: ### Cihaz önizlemesinin üzerindeki aktif ekran çubuğu \{#active-screen-bar-above-the-device-preview\} - **Screen name** — geçerli ekranın adını gösteren bir etiket. - **Toggle animations** Toggle animations — element animasyon önizlemelerini açar veya kapatır; kapatılana kadar sürekli oynatılır. Yalnızca aktif ekranda en az bir [animasyon](builder-styling#animation) olduğunda görünür. Canlı cihazdaki animasyonların görünürlüğünü etkilemez. - **Add element** Plus — geçerli ekranda [element kitaplığını](builder-elements) açar. Ekranlar ve Katmanlar panelinin üstündeki **+** düğmesiyle aynı işlevi görür; panel daraltıldığında kullanışlıdır. ### Görünüm kontrolleri (alt araç çubuğu) \{#view-controls-bottom-toolbar\} Alt araç çubuğundaki araçlar, önizlemeyi kontrol etmenizi sağlar. * **Cihaz**: Görüntü alanı boyutlarını ve cihaz çerçevesini değiştirmek için mevcut iPhone ve Android telefon modellerinden birini seçin. * **Ekran yönü**: Flow'unuzu farklı yönlerde önizlemek için dikey Portrait ve yatay Landscape modlar arasında geçiş yapın. * **Renk şeması**: Tasarımınızın farklı temalara nasıl uyum sağladığını görmek için açık Light mode ve koyu Dark mode modlar arasında geçiş yapın. * **Yerel ayar**: Flow'unuzu yerelleştirilmiş içerikle önizlemek için bir yerel ayar seçin. * **Görünüm seçenekleri**: Cihaz çerçevesini ve güvenli alan kılavuzlarını açın veya kapatın. ## Ekran ve öğe özellikleri (sağ panel) \{#screen-and-element-properties-right-panel\} ### Ekran ayarları ve düzeni \{#screen-settings-and-layout\} :::link Ana makale: [Ekranlar ve Katmanlar](paywall-layout-and-products) ::: Hiçbir öğe seçili değilken, sağ panel aktif [flow ekranının](paywall-layout-and-products) özelliklerini ayarlamanıza olanak tanır. Ayarlayabileceğiniz başlıca özellikler şunlardır: * Sistem arayüzüyle etkileşimler (ör. durum çubuğunun görünür olup olmadığı) * Otomatik düzenleme kuralları * Arka plan (renk, görsel veya video) * Dolgu boyutu * Dikey kaydırma davranışı Ekran, [interaktif quizler](onboarding-quizzes) gibi belirli öğeler içeriyorsa, bu liste ilgili özelliklerle genişler. ### Element özellikleri \{#element-properties\} Bir element seçtiğinizde, sağ panel onun stil ve etkileşim özelliklerini değiştirmenize olanak tanır. #### Tasarım özellikleri \{#design-properties\} :::link Daha fazla bilgi: [Yerleşim ve konumlandırma](manage-paywall-ui-elements), [Stiller ve görünüm](builder-styling) ::: **Design** sekmesi, seçili elementin görsel görünümünü ve yerleşimini yapılandırmanıza olanak tanır: * **Visibility**: Öğeyi göster veya gizle. Öğenin ne zaman görünür olacağını belirleyen kurallar ayarlamak için **Conditional** görünürlüğü etkinleştir. * **Position**: Relative, Absolute veya Fixed konumlandırma seçeneklerinden birini seç. * **Content** (yalnızca metin öğeleri): Öğenin metin içeriğini düzenle, [değişken](#variables) ekle ve yerelleştirmeleri yönet. * **Typography** (yalnızca metin öğeleri): Font, kalınlık, boyut, renk, hizalama, dekorasyon ve kırpma ayarlarını yapılandır. * **Spacing**: Öğenin margin ve padding değerlerini ayarla. * **Effects**: Dış gölge, iç gölge, arka plan bulanıklığı veya katman bulanıklığı ekle. * **Animation**: Animasyonlu efektler ekle (ör. Pulse) ve bunların zamanlamasını ile yoğunluğunu yapılandır. * **Appearance**: Opaklık ve döndürme ayarlarını düzenle. * **Layout**: Düzen yönü seç (dikey veya yatay) ve alt öğelerin nasıl dağıtılacağını belirle. #### Etkileşim özellikleri \{#interactions-properties\} :::link Daha fazla bilgi: [Eylemler](onboarding-actions), [Navigasyon ve Etkileşim](onboarding-navigation-branching) ::: **Interactions** sekmesi, kullanıcı seçili öğeyle etkileşime girdiğinde ne olacağını tanımlamanıza olanak tanır. Her etkileşim bir **tetikleyici** ve bir veya daha fazla **eylemden** oluşur: * **Tetikleyiciler**, *ne zaman* bir şeyin gerçekleşeceğini belirler — örneğin **On Tap** (kullanıcı elemana dokunur). * **Eylemler**, *ne olacağını* belirler — örneğin başka bir ekrana geçmek veya bir değişkenin değerini değiştirmek. Birden fazla eylemi tek bir tetikleyiciye ekleyerek sırayla zincirleyebilirsiniz. Birden fazla eylemi sırayla çalıştırmak için aynı elemana birden fazla tetikleyici ekleyebilirsiniz. ## Sol panel \{#left-panel\} Sol panel, hangi düğmenin aktif olduğuna bağlı olarak işlevini değiştirir. Şunlar arasında seçim yapabilirsiniz: * [Ekranlar ve katmanlar](#screens-and-layers) * [Öğe ekle](#element-selection) * [Ürünler](#products) * [Stiller](#saved-styles) * [Değişkenler](#variables) * [Yerelleştirme](#localization) ### Ekranlar ve Katmanlar :::link Ana makale: [Ekranlar ve Katmanlar](paywall-layout-and-products) ::: Katmanlar Layers düğmesi, Ekranlar ve Katmanlar panelini açar (flow builder'ı ilk açtığınızda varsayılan olarak gösterilir). Her ekranı katman ağacı olarak gösterir. Ekrandaki her öğe bir katmandır; container'ların içinde ise alt öğeler iç içe yer alır. Katmanları sürükleyip bırakarak sıralamalarını değiştirebilirsiniz. ### Öğe seçimi \{#element-selection\} :::link Ana makale: [Öğeler](builder-elements) ::: Artı Plus düğmesine tıklarsanız, sol panel mevcut UI öğelerini ve bunların varyasyonlarını listeler. Bir girişe tıklayarak onu mevcut ekrana yeni bir katman olarak ekleyebilirsiniz. ### Ürünler :::link Ana makale: [Ürünler](paywall-product-block) ::: Ürünler Products düğmesi ürün listesini açar. Flow'unuzdaki her ekrana hangi ürünlerin atandığını gösterir. Bu liste yalnızca okunabilir. Bir ekrana ürün atamak için Ürün öğesi ekleyin ve sağ panelden yapılandırın. Ürün oluşturmak veya düzenlemek için Adapty Kontrol Paneli'ndeki **Products** sayfasını kullanın. ### Kaydedilmiş stiller \{#saved-styles\} :::info Daha fazla bilgi: - [Stiller ve görünüm](builder-styling) - [Metin içeriği](onboarding-text) - [Karanlık mod](paywall-dark-mode) ::: Stiller Styles düğmesi Kaydedilmiş Stilleri açar. Burada global stilleri düzenleyip yönetebilirsiniz. Flow'unuzdaki birden fazla öğe aynı tipografiyi veya rengi kullanıyorsa bu verileri global stil olarak kaydedebilirsiniz. Ardından tek bir tıklamayla yeniden kullanabilirsiniz. Şu anda Flow Builder, iki tür global stil desteklemektedir: Yazı tipi stilleri ve Renk stilleri. Her Renk stilinin isteğe bağlı olarak Karanlık mod için ayrı bir değeri olabilir. ### Değişkenler :::link Ana makale: [Değişkenler](onboarding-variables) ::: Köşeli parantez Variables düğmesi Değişkenler panelini açar. Burada flow'unuz için değişken oluşturabilir ve yönetebilirsiniz. Çalışma zamanında SDK, değişken yer tutucularını gerçek değerlerle değiştirir — kullanıcı özellikleri, ürün fiyatları, yerelleştirilmiş metinler ve daha fazlası. Değişkenler iki sekme altında gruplandırılmıştır: * **Özel**: Eylemler aracılığıyla oluşturup yönettiğiniz değişkenler. * **Elementler**: Kullanıcı etkileşimiyle belirlenen değerler — sınav yanıtları, toggle durumları veya sekme seçimi gibi. Ürün değişkenleri — fiyat, ad ve diğer ürün verileri — bu panelde listelenmez. Bunlara bir metin elementini düzenlerken doğrudan başvurabilirsiniz. Değişkenleri şunlar için kullanabilirsiniz: * **Metin bağlama**: Statik dizeler yerine dinamik içerik gösterin. * **Görünürlüğü kontrol etme**: Koşullara göre öğeleri gösterin veya gizleyin (örneğin, premium kullanıcılar için yükseltme düğmesini gizleyin). * **Kullanıcıyla etkileşim**: Form veya sınav gibi kullanıcı giriş alanlarından verilere erişin. ### Yerelleştirme \{#localization\} :::link Ana makale: [Yerelleştirme](add-flow-remote-config-locale) ::: Yerelleştirme görünümü, flow'unuzdaki tüm çevrilebilir içerikleri yönetmenizi sağlar. Her metin dizesini ve görseli ekrana göre düzenlenmiş bir tabloda, her yerel ayar için ayrı sütunlarla gösterir. Bu görünümden şunları yapabilirsiniz: * Yeni yerel ayarlar ekleyebilir ve yerelleştirilmiş dizeleri satır içinde düzenleyebilirsiniz. * Çeviri durumunu takip edebilirsiniz — her satır **Done** veya **Missing** olarak işaretlenir. * Ekrana göre filtreleyebilir ya da yalnızca eksik çevirileri gösterebilirsiniz. * İçerikleri otomatik çevirmek için **AI Translate**'i, toplu çeviri aktarmak için ise **Import/Export**'u kullanabilirsiniz. --- # File: flow-builder-recipes --- --- title: "Yaygın flow tarifleri" description: "Flow Builder'da yaygın ekran şablonları oluşturmak için adım adım kılavuzlar." --- Bu bölümde Flow Builder'daki en yaygın ekran şablonlarının nasıl oluşturulacağı anlatılıyor — düzen seçimlerinden etkileşimlere kadar her şey, öğe öğe. Her kılavuz bağımsız olup standart Flow Builder öğelerini kullanır. <CustomDocCardList /> Temel bir kişiselleştirilmiş flow oluşturmak için bu hızlı başlangıç videosunu izleyin: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/aa-m459VIuY?si=zN_Co6B6qB88UPZP" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> :::link Flow oluşturma hakkında daha fazla bilgi edinmek ister misiniz? [YouTube oynatma listemizde](https://www.youtube.com/playlist?list=PLMksWqaZiWtM) adım adım video eğitimlerini izleyin. ::: --- # File: basic-paywall-screen --- --- title: "Temel bir paywall ekranı oluşturma" description: "Flow Builder'da standart bir paywall ekranı oluşturmak için adım adım kılavuz." --- Bu, en yaygın kullanılan paywall şablonudur. Bağımsız bir ekran olarak kullanabilir ya da çok ekranlı bir [flow](adapty-flow-builder)'un sonuna ekleyebilirsiniz. Standart bir paywall ekranı; bir başlık, bir değer açıklaması, bir özellik listesi, bir ürün listesi, bir satın alma düğmesi ve satın almaları geri yükleme, kullanım koşulları ve gizlilik politikasına yönelik alt bağlantılar içerir. ## Başlamadan önce \{#before-you-start\} - Adapty Kontrol Paneli'nde [ürün oluşturun](create-product). - [Adapty'yi App Store ve Google Play'e bağlayın](integrate-payments). ## 1. Yeniden kullanılabilir stilleri ayarlayın \{#1-set-up-reusable-styles\} Yeniden kullanılabilir stiller, tek bir tıklamayla her ekranda aynı tipografi ve renkleri uygulamanızı sağlar. Her yeni flow, bir dizi varsayılan metin stiliyle (H1, Body, Button Label vb.) gelir — öğe eklemeye başlamadan önce bunları tasarımınıza göre düzenleyin. Ekran genelinde kullanacağınız marka renkleri için renk stilleri ekleyin. Ayrıntılı talimatlar için bkz. [Stiller ve görünüm — Yeniden kullanılabilir stiller](builder-styling#reusable-styles). Stilleri ayarlamak için: 1. Sol panelde **Styles** Styles panelini açın. 2. **Text** sekmesinde, mevcut bir stile tıklayarak font, kalınlık, boyut ve rengi düzenleyin. Yalnızca varsayılanlar ihtiyacınızı karşılamıyorsa yeni stiller ekleyin. 3. **Colors** sekmesinde **Plus Create style** seçeneğine tıklayın ve ekranda tekrar kullanmayı planladığınız renkleri ekleyin. ## 2. Ekran düzenini ayarlayın \{#set-up-the-screen-layout\} Ekranın kendisi, eklediğiniz her şey için bir kapsayıcı işlevi görür. Daha sonra eklediğiniz öğelerin düzgün dağılması için önce ekranın düzenini, arka planını ve dolgu ayarlarını yapılandırın. Ekran özelliklerinin tam listesi için bkz. [Ekranlar ve katmanlar — Ekran ayarları](paywall-layout-and-products#screen-settings). Ekranı yapılandırmak için: 1. Ekranı seçmek için canvas'ın boş bir alanına tıklayın. Sağ panel, ekran ayarlarına geçer. 2. **System UI** altında, içerik ekran kenarlarına kadar uzansın diye **Safe area** seçeneğini devre dışı bırakın. 3. **Layout** altında, yönü **Vertical** Vertical ve dağılımı **Space evenly** olarak ayarlayın. 4. **Fill** altında bir arka plan türü seçin — düz renk, gradyan veya resim. Bu örnekte iki renk durağına sahip bir **Gradient** Gradient kullanılmaktadır. ## 3. Kapat düğmesini ekle \{#add-the-close-button\} Kapat düğmesi, paywallı kapatır. **Close** hazır ayarı önceden yapılandırılmış olarak gelir — herhangi bir eylem kurulumu gerekmez. 1. Canvas üzerinde **+** simgesine tıklayın. 2. **Buttons** > **Close** seçeneğini seçin. ## 4. Başlığı ekleyin ve kapat düğmesiyle eşleştirin \{#add-the-title-and-pair-it-with-the-close-button\} H1, ekranın üst kısmındaki kapat düğmesinin yanına yerleşir. İkisini yatay hizalamak için bir yatay kapsayıcıya sarın. Başlığı eklemek için: 1. **+** > **Text** > **H1** yolunu izleyin. 2. H1 seçiliyken sağ panelde **Design** sekmesini açın ve **Content** alanındaki metni düzenleyin. Başlığı kapat düğmesiyle gruplamak için: 1. **Layers** panelinde, kapat düğmesi katmanının üç nokta menüsüne Context menu tıklayın ve **Wrap** > **Wrap in Horizontal Container** seçeneğini seçin. 2. H1 katmanını yeni yatay kapsayıcıya sürükleyin. İki öğeyi hizalamak için: 1. Kapat düğmesinin ve H1 yazı tipi boyutunu, aynı satırda rahat bir şekilde yer alacak şekilde ayarlayın. 2. Yatay kapsayıcı seçiliyken, öğelerin doğru şekilde hizalanması için sağ paneldeki hizalama ve dağılım ayarlarını yapın. ## 5. Değer açıklamasını ekleyin \{#add-the-value-description\} Başlığın altındaki kısa bir gövde satırı, kullanıcının abonelikten ne kazanacağını açıklar. 1. **+** > **Text** > **Body** seçeneğine tıklayın. 2. Gövde öğesi seçiliyken **Design** sekmesindeki **Content** alanında metni düzenleyin. ## 6. Özellik listesini ekleyin \{#add-the-feature-list\} Özellik listesi, aboneliğin kilidini açmanın neler içerdiğini vurgular. Her satırda bir ikon, bir özellik başlığı ve kısa bir açıklama bulunur. Liste ön ayarlarının tam seti için [Elements — List](builder-elements#list) bölümüne bakın. Özellik listesini eklemek için: 1. **+** > **List** seçeneğine tıklayın ve bir liste ön ayarı seçin. Icon List, paywall'lar için en yaygın kullanılanıdır. 2. Her satır seçiliyken başlık ve açıklamayı **Content** alanından düzenleyin. 3. Satır eklemek veya kaldırmak için listeyi seçin ve **Layers** panelindeki satır kontrollerini kullanın. ## 7. Ürün listesini ekleyin \{#add-the-product-list\} Ürün listesi, kullanıcının seçebileceği abonelik seçeneklerini gösterir. Products öğesi, ekrana atanan her ürün için bir kart oluşturur ve kartlardan biri otomatik olarak varsayılan olarak işaretlenir. Ürün yönetimi hakkında daha fazla bilgi için bkz. [Satın almaları ayarlama](paywall-product-block). Ürünleri eklemek ve yapılandırmak için: 1. **+** > **Products** seçeneğine tıklayın ve bir düzen şablonu seçin. Dikey Liste en yaygın kullanılanıdır. 2. Tuval üzerindeki her ürün kartını seçin ve **Design** sekmesindeki açılır menüden bir ürün seçin. Açılır menüde Adapty Kontrol Paneli'nde yapılandırılmış tüm ürünler gösterilir. 3. Varsayılan seçimi değiştirmek için istediğiniz kartı seçin ve **Design** sekmesinde **Set as default product** seçeneğini etkinleştirin. 4. İndirim rozetini özelleştirmek için **Layers** panelinde bir ürün kartını genişletin, rozet katmanını seçin ve **Content** alanında metnini düzenleyin. Diğer kartlardaki rozeti gizlemek için her rozet katmanının yanındaki göz simgesine Show tıklayın. ## 8. Satın alma düğmesini ekleyin \{#add-the-purchase-button\} Satın alma düğmesi, kullanıcının seçtiği ürün için uygulama içi satın alma işlemini başlatır. `products.selectedProduct` değişkeni her zaman ekranda o an seçili olan ürünü döndürür. Satın alma düğmesini eklemek için: 1. **+** > **Buttons** seçeneğine tıklayın ve bir düğme şablonu seçin. 2. Düğme seçiliyken sağ panelden **Interactions** sekmesini açın. 3. **Add trigger** > **On tap** seçeneğine tıklayın, ardından **Add action** seçeneğine tıklayın. 4. **Action** alanını **Purchase**, **Product** alanını ise `products.selectedProduct` olarak ayarlayın. ## 9. Alt bilgi bağlantıları ekleyin \{#add-footer-links\} Alt bilgi; kullanım koşulları ve gizlilik politikası bağlantılarını (uygulama mağazaları tarafından zorunlu tutulmaktadır) ve önceki satın alımları geri yüklemek için bir düğme içerir. Alt bilgi bağlantılarını eklemek için: 1. Click **+** > **Buttons** > **Links**. This adds a row with Restore Purchases, Terms of Use, and Privacy Policy. 2. In the **Layers** panel, select the **Terms of Use** button. Open the **Interactions** tab — the **Open URL** action is already attached. Click the action and enter the target URL. 3. Repeat for the **Privacy Policy** button with your privacy URL. 4. Leave the **Restore Purchases** button as is. Its action is preconfigured. :::tip If any element's positioning feels too high or low, or if you want to add more space anywhere, adjust the element's margins and padding. ::: ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). --- # File: show-plans-bottom-sheet --- --- title: "Tüm planları bir alt sayfada göster" description: "Tek bir CTA, 'Tüm planları göster' bağlantısı ve tam ürün listesini ortaya çıkaran bir alt sayfa içeren bir hero paywall oluşturun." --- Bu şablon, önce tek bir öne çıkan teklif sunar ve tam plan listesine giden sade bir bağlantı içerir. **Show all plans** bağlantısına dokunulduğunda, diğer ürünleri, bir satın alma düğmesini ve altbilgi bağlantılarını içeren bir alt sayfa yukarı kayar. Bir plan orantısız biçimde iyi dönüşüm sağladığında kullanın — alt sayfa, ana ekranı kalabalıklaştırmadan alternatifleri tek dokunuş uzağında tutar. ## Başlamadan önce \{#before-you-start\} - Adapty Kontrol Paneli'nde [ürün oluşturun](create-product). - [Adapty'yi App Store ve Google Play'e bağlayın](integrate-payments). ## 1. Ekran düzenini ayarlayın \{#set-up-the-screen-layout\} Hero görseli ekranın arka planı olarak kullanın ve içeriğin geri kalanını alt kısımda gruplayın; böylece görsel ekranın üst bölümünü dolduracaktır. Ekran özelliklerinin tam listesi için bkz. [Ekranlar ve katmanlar — Ekran ayarları](paywall-layout-and-products#screen-settings). Ekranı yapılandırmak için: 1. Ekranı seçmek için canvas'ın boş bir alanına tıklayın. 2. **System UI** altında, kahraman görselinin ekran kenarlarına kadar uzanması için **Safe area** seçeneğini devre dışı bırakın. 3. **Fill** altında **Image** Image seçeneğini belirleyin ve kahraman görselinizi yükleyin. 4. **Layout** altında, içeriği istediğiniz yere sabitlemek için yön, boşluk ve hizalama ayarlarını yapılandırın. Bu şablonda, küçük bir boşlukla **Vertical** Vertical yönü ve **bottom-middle** hizalaması, başlık ile düğmeleri ekranın alt kısmında gruplar. ## 2. CTA başlığı ekle \{#add-the-cta-heading\} Başlık, ekranın alt kısmında, abone ol butonunun hemen üzerinde yer alır. Hero görseli ise üstteki alanı kaplar. 1. **+** > **Text** > **H1** seçeneğine tıklayın. 2. H1 seçili durumdayken **Design** sekmesini açın ve metni **Content** alanında düzenleyin. ## 3. Alt sayfayı ve başlığını ekleyin \{#add-the-bottom-sheet-and-its-title\} Alt sayfa, ekranın altından yukarı doğru kayan bir düzen kapsayıcısıdır. Şimdilik görünür olarak ekleyin; sonraki birkaç adımda içeriğini dolduracak ve her şey yerli yerinde olunca gizleyeceksiniz. Gizli öğeler düzenlenemez, bu yüzden içeriği tamamlayana kadar sayfanın görünür kalması gerekir. Alt sayfalar ve diğer düzen kapsayıcıları hakkında daha fazla bilgi için bkz. [Öğeler — Düzen](builder-elements#layout). Alt sayfayı ve başlığını eklemek için: 1. **+** > **Layout** > **Bottom Sheet** seçeneğine tıklayın. 2. **Layers** panelinde bottom sheet'i genişletin, **Title** katmanını seçin ve **Design** sekmesindeki **Content** alanını düzenleyin — örneğin `Choose your plan`. ## 4. Alt sayfanın içine ürün listesini ekleyin \{#4-add-the-product-list-inside-the-bottom-sheet\} Tüm ürünleri alt sayfanın içine yerleştirin. Bu ürünlerden biri, ana CTA düğmesinde gösterilen fiyatı da belirleyecek. Ürün yönetimi hakkında daha fazla bilgi için [Satın alma işlemlerini ayarlama](paywall-product-block) konusuna bakın. Ürün eklemek ve yapılandırmak için: 1. **+** > **Products** seçeneğine tıklayın ve bir düzen şablonu seçin. Dikey Liste çoğu durumda iyi çalışır. Öğe, alt sayfanın dışında ekranda görünür. 2. **Layers** panelinde, Products katmanını alt sayfanın içindeki **Content** konteynerine sürükleyin. 3. Tuvaldeki her ürün kartını seçin ve **Design** sekmesindeki açılır listeden bir ürün seçin. ## 5. Alt sayfaya satın alma düğmesi ekleyin \{#add-the-purchase-button-inside-the-bottom-sheet\} Alt sayfanın, kullanıcının listeden seçtiği planı satın almak için kendi satın alma düğmesine ihtiyacı vardır. 1. **+** > **Buttons** seçeneğine tıklayın ve bir düğme ön ayarı seçin. 2. **Layers** panelinde, yeni düğmeyi alt sayfanın içindeki **Content** kapsayıcısına sürükleyin. 3. Butonu seçili haldeyken sağ panelde **Interactions** sekmesini açın. 4. **Add trigger** > **On tap** seçeneğine tıklayın, ardından **Add action** butonuna tıklayın. 5. **Action** alanını **Purchase**, **Product** alanını `products.selectedProduct` olarak ayarlayın. ## 6. Alt sayfanın içine footer bağlantıları ekleyin \{#add-the-footer-links-inside-the-bottom-sheet\} :::important Buton içine yerleştirilmiş metinlerde [satır içi bağlantılar](onboarding-text#inline-link) kullanmayın. Bunun yerine butonun üzerinde **Open URL** eylemini ayarlayın. ::: Kullanım koşulları, gizlilik politikası ve satın almaları geri yükleme seçeneği sayfanın alt kısmında yer alır; bu sayede ana ekran sade kalır. 1. **+** > **Buttons** > **Links** seçeneğine tıklayın. Bu, Restore Purchases, Terms of Use ve Privacy Policy içeren bir satır ekler. 2. **Layers** panelinde, Links satırını alt sayfanın içindeki **Content** kapsayıcısına sürükleyin. 3. **Layers** panelinde, **Terms of Use** butonunu seçin. **Interactions** sekmesini açın ve kullanım koşulları URL'nizi **Open URL** alanına yapıştırın. 4. Gizlilik URL'niz için **Privacy Policy** butonuyla aynı adımı tekrarlayın. 5. **Restore Purchases** bağlantısını olduğu gibi bırakın. Bu bağlantının eylemi önceden yapılandırılmıştır. ## 7. Alt sayfayı gizleyin \{#hide-the-bottom-sheet\} Sayfanın içeriği hazır olduğuna göre, varsayılan olarak ekranda görünmemesi için gizleyin. Kullanıcılar son adımda **Show all plans** seçeneğine dokunarak sayfayı açacak. **Layers** panelinde alt sayfayı seçin ve durumunu **Hide** Hide olarak ayarlayın. Sayfa katman ağacında kalmaya devam eder ancak tuval üzerinde artık görüntülenmez. ## 8. Ana abone olma düğmesini ekle \{#add-the-main-subscribe-button\} Ekrandaki ana düğme, kullanıcıyı tek dokunuşla aylık plana abone eder. Etiketinde aylık ürünün fiyat değişkeni kullanılır; böylece düğme her zaman ürünle senkronize kalır. 1. **Layers** panelinde ekrana tıklayın; böylece yeni öğeler alt sayfanın içine değil, köke eklenir. 2. **+** > **Buttons** seçeneğine tıklayın ve bir düğme ön ayarı seçin. 3. Düğme seçiliyken **Design** sekmesini açın ve imleci **Content** alanına getirin. Variable icon simgesine tıklayıp ana ürün için fiyat değişkenini seçin. Geri kalan etiketi çevresine ekleyin — örneğin, `Subscribe for {price}/month`. 4. **Interactions** sekmesine geçin ve **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın. 5. **Action** alanını **Purchase**, **Product** alanını ise ihtiyacınız olan ürüne ayarlayın. Alt sayfa butonunun aksine bu buton, `products.selectedProduct` yerine belirli bir ürünü hedefler. ## 9. 'Tüm planları göster' bağlantısını ekleyin \{#add-the-show-all-plans-link\} Abone ol düğmesinin altındaki bir metin bağlantısı, dokunulduğunda alt sayfayı açar. Bunu **Button Label** stiliyle bir metin öğesi olarak eklemek, bir aksiyon bağlamanıza olanak tanırken görünümü sade tutar. Göster/Gizle aksiyonu hakkında daha fazla bilgi için bkz. [Aksiyonlar — Öğeleri göster/gizle](onboarding-actions#showhide-elements). Bağlantıyı eklemek için: 1. **Layers** panelinde ekran seçiliyken **+** > **Text** > **Button Label** seçeneğine tıklayın. 2. Metin öğesi seçiliyken **Content** alanını `Show all plans` olarak düzenleyin. 3. **Interactions** sekmesini açın ve **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın. 4. **Action** değerini **Show** olarak ayarlayın ve açılır listeden bottom sheet öğesini seçin. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). --- # File: paywall-with-tabs --- --- title: "Sekmeli paywall oluşturma" description: "İki sekme arasında geçiş yaparak farklı özellik listelerini, ürün gruplarını ve satın alma eylemlerini gösteren bir paywall ekranı oluşturun." --- Bu şablon, tek bir ekranda aynı teklifin iki varyantı arasında geçiş yapmak için sekmeleri kullanır. Her sekme kendi özellik listesini, ürün listesini ve satın alma düğmesini içerir. Bir sekmeye dokunulduğunda ekrandan çıkmadan görünen içerik değişir; bu da planları katmana, fatura dönemine veya kitle segmentine göre ayırmak için oldukça kullanışlıdır. ## Başlamadan önce \{#before-you-start\} - Adapty Kontrol Paneli'nde [ürün oluşturun](create-product). - [Adapty'yi App Store ve Google Play'e bağlayın](integrate-payments). ## 1. Ekran düzenini ayarla \{#set-up-the-screen-layout\} Ekran; kapat düğmesi, başlık, sekmeler ve sekme içerikleri için bir kapsayıcı görevi görür. Bu örnekte arka plan bir görsel kullanılarak ayarlanmıştır, ancak düz renk veya gradyan da aynı şekilde çalışır. Ekran özelliklerinin tam listesi için bkz. [Ekranlar ve katmanlar — Ekran ayarları](paywall-layout-and-products#screen-settings). Ekranı yapılandırmak için: 1. Kanvasın boş bir alanına tıklayarak ekranı seçin. 2. **System UI** altında, arka planın ekranın kenarlarına kadar uzanması için **Safe area** seçeneğini devre dışı bırakın. 3. **Fill** altında bir arka plan türü seçin ve yapılandırın. Bu örnekte bir **Image** Image kullanılmıştır; ancak düz renk veya gradyan da aynı şekilde çalışır. 4. **Layout** altında yönü **Vertical** Vertical olarak ayarlayın; sekme içeriği kalan alanı dolduracak şekilde öğelerin üstten alta sıralanması için boşluk ve hizalamayı yapılandırın. ## 2. Kapat butonunu ekleyin \{#add-the-close-button\} Kapat butonu, paywall'ı kapatır. **Close** ön ayarı önceden yapılandırılmıştır — herhangi bir eylem ayarı gerekmez. 1. Canvas üzerinde **+** simgesine tıklayın. 2. **Buttons** > **Close** seçeneğini seçin. ## 3. Başlık ekle ve kapat düğmesiyle eşleştir \{#add-the-title-and-pair-it-with-the-close-button\} Başlık, ekranın üst kısmında kapat düğmesinin yanında yer alır. İkisini yatay olarak hizalamak için her ikisini de bir yatay kapsayıcıya sar. Başlık eklemek için: 1. **+** > **Text** > **H1** seçeneğine tıkla. 2. H1 seçiliyken **Design** sekmesini aç ve **Content** alanındaki metni düzenle. Başlığı kapat düğmesiyle gruplamak için: 1. **Layers** panelinde, kapat düğmesi katmanındaki üç nokta menüsüne Context menu tıklayın ve **Wrap** > **Wrap in Horizontal Container** seçeneğini seçin. 2. H1 katmanını yeni yatay container'a sürükleyin. İki öğeyi hizalamak için: 1. Kapat düğmesinin boyutunu ve H1 yazı tipi boyutunu, ikisi aynı satırda rahat duracak şekilde ayarlayın. 2. Yatay container seçiliyken, sağ paneldeki hizalama ve dağılım ayarlarını yaparak öğelerin doğru şekilde sıralanmasını sağlayın. ## 4. Sekmeleri ekleyin ve etiketlerini yapılandırın \{#add-the-tabs-and-configure-their-labels\} Sekmeler elementi, bir ekran bölümünü birbirine geçiş yapılabilir içerik panellerine böler. Her sekme, kullanıcı o sekmeyi seçtiğinde görünen kendi içerik kapsayıcısına sahiptir. Sekmeler elementi hakkında daha fazla bilgi için bkz. [Elementler — Sekmeler](builder-elements#tabs). Seçilebilir gruplar hakkında daha fazla bilgi için bkz. [Seçilebilir elementler ve gruplar](flow-selectable-elements). Sekmeleri eklemek için: 1. **+** > **Tabs** seçeneğine tıklayın ve bir ön ayar seçin — Segment control, Button Tabs veya Underline. 2. Her sekmenin adı canvas üzerinde veya **Layers** panelinde seçiliyken, etiketi değiştirmek için **Design** sekmesindeki **Content** alanını düzenleyin — örneğin `Premium` ve `Pro`. ## 5. İlk sekmeye özellik listesi ekle \{#add-a-feature-list-to-the-first-tab\} İlk sekmenin içinde kısa ve sade bir özellik listesi, kullanıcılara o planın neler sunduğunu gösterir. Listenin tüm hazır şablonları için [Öğeler — List](builder-elements#list) sayfasına bakın. Özellik listesini eklemek için: 1. **+** > **List** seçeneğine tıklayın ve bir liste şablonu seçin. Paywall'lar için en sade seçenek Icon List'tir. Öğe, katman ağacının sonuna eklenir. 2. Her satırı seçerek başlığı **Content** alanından düzenleyin. 3. **Katmanlar** panelinde, listeyi ilk sekmenin **Content** kapsayıcısına sürükleyin. ## 6. İlk sekmeye ürün listesini ekleyin \{#add-the-product-list-to-the-first-tab\} Ürün listesi, ilk sekmedeki abonelik seçeneklerini gösterir. Products öğesi, ekrana atanan her ürün için bir kart oluşturur ve kendi seçilebilir grubunu yaratır. Ürün yönetimi hakkında daha fazla bilgi için bkz. [Satın almaları ayarlama](paywall-product-block). Ürün eklemek ve yapılandırmak için: 1. **+** > **Products** seçeneğine tıklayın ve bir düzen ön ayarı seçin. Dikey Liste, üst üste sıralanmış planlar için iyi çalışır. Öğe, katman ağacının sonunda görünür. 2. Tuvaldeki her ürün kartını seçin ve **Design** sekmesindeki açılır menüden bir ürün seçin. 3. **Layers** panelinde, Products katmanını ilk sekmenin **Content** kapsayıcısına sürükleyin. ## 7. Satın alma butonunu ilk sekmeye ekle \{#add-the-purchase-button-to-the-first-tab\} Satın alma butonu, kullanıcının ilk sekmede seçtiği ürün için uygulama içi satın almayı başlatır. Butonun etiketi, seçili ürünün fiyatını gösterdiğinden kullanıcının seçimiyle her zaman senkronize kalır. Satın alma eylemi hakkında daha fazla bilgi için bkz. [Eylemler — Satın Alma](onboarding-actions#purchase). Satın alma butonunu eklemek ve yapılandırmak için: 1. **+** > **Buttons** seçeneğine tıklayın ve bir buton ön ayarı seçin. Öğe, katman ağacının sonunda görünür. 2. Butonu seçili durumdayken **Design** sekmesini açın ve imleci **Content** alanına getirin. Değişken simgesine Variable icon tıklayın, `products.selectedProduct` seçeneğini, ardından `prod_price` özelliğini seçin — tam değişken `products.selectedProduct.prod_price` olarak çözümlenir. Etiketin geri kalanıyla çevreyin — örneğin, `Subscribe for {prod_price}`. 3. **Interactions** sekmesine geçin ve **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın. 4. **Action** kısmını **Purchase**, **Product** kısmını ise `products.selectedProduct` olarak ayarlayın. 5. **Layers** panelinde, butonu birinci sekmenin **Content** container'ına sürükleyin. ## 8. İlk sekmenin içeriğini ikinci sekmeye kopyalayın \{#copy-the-first-tabs-content-into-the-second-tab\} Aynı yapıyı sıfırdan yeniden oluşturmak yerine, birinci sekmedeki özellik listesini, ürün listesini ve satın alma düğmesini ikinci sekmeye kopyalayın. Bundan sonra yalnızca değerleri güncellemeniz yeterli olacak. İçeriği kopyalamak için: 1. **Layers** panelinde, birinci sekmenin **Content** kapsayıcısını genişletin. 2. İçindeki her öğeyi (özellik listesi, ürünler, satın alma butonu) seçin, ⌘C / Ctrl+C ile kopyalayın ve ⌘V / Ctrl+V ile yapıştırın. Kopyalar katman ağacının sonunda görünür. 3. Kopyalanan her öğeyi ikinci sekmenin **Content** kapsayıcısına sürükleyin. ## 9. İkinci sekmenin içeriğini güncelleme \{#update-the-second-tabs-content\} İkinci sekme şu an birincinin aynısını gösteriyor. Her öğeyi ikinci planı yansıtacak şekilde güncelleyin. İkinci sekmeyi güncellemek için: 1. İkinci sekmedeki özellik listesini düzenleyerek satırların ikinci planın özelliklerini yansıtmasını sağlayın. 2. İkinci sekmedeki Products öğesinde her bir ürün kartını seçin ve açılır menüden ikinci planın ürünlerini atayın. Bu Products öğesi otomatik olarak ayrı bir seçilebilir grup (`products2`) haline gelir. 3. İkinci sekmedeki satın alma düğmesini seçin. **Design** sekmesindeki **Content** alanında fiyat değişkenini `products.selectedProduct.prod_price` yerine `products2.selectedProduct.prod_price` olarak değiştirin. 4. **Interactions** sekmesine geçin ve **Purchase** eylemindeki **Product** değerini `products.selectedProduct` yerine `products2.selectedProduct` olarak güncelleyin. ## 10. Alt bilgi bağlantılarını ekle \{#add-the-shared-footer-links\} Kullanım koşulları, gizlilik politikası ve satın almaları geri yükle bağlantıları, hangi sekme aktif olursa olsun her zaman görünür kalır. Bu bağlantıları her iki sekme içerik kapsayıcısının da dışına — ekran düzeyine — ekle ki her iki sekme arasında ortak kullanılsın. Alt bilgi bağlantılarını eklemek için: 1. **+** > **Buttons** > **Links** seçeneğine tıklayın. Bu adım, katman ağacının sonuna Restore Purchases, Terms of Use ve Privacy Policy içeren bir satır ekler; bu tam istediğiniz yer — ekranın köküne yerleştirilmiş, bir sekmenin içine gömülmemiş. 2. **Layers** panelinde **Terms of Use** butonunu seçin. **Interactions** sekmesini açın ve kullanım koşulları URL'nizi **Open URL** alanına yapıştırın. 3. Aynı işlemi **Privacy Policy** butonu için gizlilik URL'nizi kullanarak tekrarlayın. 4. **Restore Purchases** bağlantısını olduğu gibi bırakın. Eylemi önceden yapılandırılmıştır. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - [Flow'u bir placement'a ekleyin](create-placement) ve kullanıcılara göstermeye başlayın. --- # File: paywall-features-per-product --- --- title: "Ürüne göre farklı özellikler gösterme" description: "Koşullu görünürlük kullanarak kullanıcının seçtiği ürüne bağlı olarak farklı özellik listesi gösterin." --- Bu şablon, farklı planlar için farklı özellik listelerini vurgulamak amacıyla koşullu görünürlük kullanır. Ekranda iki ürün gösterilir — örneğin Pro ve Pro+ — ve kullanıcının seçtiği ürüne bağlı olarak farklı bir özellik listesi görünür. Ürünlerden biri varsayılan olarak işaretlendiğinden, ekran ilk yüklendiğinde o ürünün özellik listesi görünür olur. ## Başlamadan önce \{#before-you-start\} - Adapty Kontrol Paneli'nde [ürün oluşturun](create-product). - [Adapty'yi App Store ve Google Play'e bağlayın](integrate-payments). ## 1. Ekran düzenini ayarlayın \{#1-set-up-the-screen-layout\} Ekran, eklediğiniz her şeyin bir kapsayıcısı olarak işlev görür. Bu örnekte arka plan bir resimdir, ancak düz renk veya gradyan da aynı şekilde çalışır. Ekran özelliklerinin tam listesi için bkz. [Ekranlar ve katmanlar — Ekran ayarları](paywall-layout-and-products#screen-settings). Ekranı yapılandırmak için: 1. Tuvalde boş bir alana tıklayarak ekranı seçin. 2. **System UI** altında, arka planın ekran kenarlarına kadar uzanması için **Safe area** seçeneğini devre dışı bırakın. 3. **Fill** altında bir arka plan türü seçin ve yapılandırın. Bu örnekte **Image** Image kullanılmaktadır; düz renk veya gradyan da aynı şekilde çalışır. 4. **Layout** altında yönü **Vertical** Vertical olarak ayarlayın; öğelerin üstten alta dizilmesi ve içeriğin kalan alanı doldurması için boşluk ve hizalama ayarlarını yapılandırın. ## 2. Kapat düğmesini ekleyin \{#add-the-close-button\} Kapat düğmesi paywallı kapatır. **Close** hazır ayarı önceden yapılandırılmıştır — herhangi bir işlem kurulumu gerekmez. 1. Tuval üzerinde **+** simgesine tıklayın. 2. **Buttons** > **Close** seçeneğini seçin. ## 3. Başlığı ekle ve kapat düğmesiyle eşleştir \{#add-the-title-and-pair-it-with-the-close-button\} Başlık, ekranın üst kısmındaki kapat düğmesinin yanında yer alır. İkisini yatay olarak hizalamak için her ikisini de yatay bir kapsayıcıya sarmalayın. Başlığı eklemek için: 1. **+** > **Text** > **H1** seçeneğine tıklayın. 2. H1 seçiliyken **Design** sekmesini açın ve **Content** alanındaki metni düzenleyin. Başlığı kapat düğmesiyle gruplamak için: 1. **Layers** panelinde, kapat düğmesi katmanının üç nokta menüsüne Context menu tıklayın ve **Wrap** > **Wrap in Horizontal Container** seçeneğini seçin. 2. H1 katmanını yeni yatay container'ın içine sürükleyin. İki öğeyi hizalamak için: 1. Kapat düğmesinin boyutunu ve H1 yazı tipi boyutunu aynı satırda rahatça yer alacak şekilde ayarlayın. 2. Yatay kapsayıcı seçiliyken, sağ paneldeki hizalama ve dağılım ayarlarını öğeler doğru şekilde sıralanacak biçimde yapılandırın. ## 4. Ürün listesini ekle \{#add-the-product-list\} Kullanıcının seçebileceği ürünleri ekle. Ekran ilk yüklendiğinde anlamlı bir durumda açılması için bunlardan birini varsayılan olarak işaretle. Ürünleri yönetme hakkında daha fazla bilgi için bkz. [Satın almaları ayarla](paywall-product-block). Ürün eklemek ve yapılandırmak için: 1. **+** > **Products** seçeneğine tıklayın ve bir düzen şablonu seçin. Bu şablon için Dikey Liste iyi çalışır. 2. Tuvaldeki her ürün kartını seçin ve **Design** sekmesindeki açılır menüden bir ürün seçin. 3. Varsayılan olarak seçili olmasını istediğiniz kartı seçin — örneğin Pro+ — ve **Design** sekmesinde **Set as default product** seçeneğini etkinleştirin. ## 5. İlk ürün için özellik listesi ekleme \{#add-the-feature-list-for-the-first-product\} İlk özellik listesi varsayılan ürünü açıklar. Yalnızca kullanıcı birinci ürünü seçtiğinde görünür. Koşullu görünürlük hakkında daha fazla bilgi için bkz. [Koşullu görünürlük](onboarding-element-visibility). :::tip İki ayrı liste kullanmak yerine tek bir liste ekleyip içindeki metin öğelerini koşullu hale getirebilirsiniz; böylece liste seçilen ürüne göre uyum sağlar. Bkz. [Koşullu metin ekleme](onboarding-text#add-conditional-text). ::: Özellik listesini eklemek ve yapılandırmak için: 1. **+** > **List** seçeneğine tıklayın ve kompakt bir liste şablonu seçin. İkon listesi paywall'lar için iyi çalışır. 2. Her satır seçiliyken, **Content** alanındaki başlığı düzenleyerek ilk ürünün özelliklerini tanımlayın. 3. Liste seçiliyken **Design** sekmesini açın. **Visibility** altında **Conditional** Conditional seçeneğini seçin. 4. Koşulu, liste yalnızca ilk ürün seçili olan ürün olduğunda gösterilecek şekilde ayarlayın. `products.selectedProduct.prod_title` değişkeniyle eşleştirin. **Value** için değişken simgesine `{}` tıklayın, ilk ürün kartını seçin, ardından `prod_title` özniteliğini seçin — karşılaştırma, o ürünün başlığına karşılık gelir. ## 6. İkinci ürün için özellik listesi ekleme \{#add-the-feature-list-for-the-second-product\} İkinci ürün için de aynı adımları tekrarlayın. İki liste birbirini dışlar; yani aynı anda yalnızca biri görünür — hangisinin görüneceği seçili ürüne göre belirlenir. İkinci özellik listesini eklemek için: 1. **+** > **List** düğmesine tıklayın ve görsel tutarlılık için aynı kompakt ön ayarı seçin. 2. İkinci ürünün özelliklerini tanımlamak için her satırı düzenleyin. 3. **Visibility** altında **Conditional** Conditional seçeneğini seçin ve 5. adımdakiyle aynı koşulu ayarlayın; ancak **Value** değişken seçicisini ikinci ürün kartının `prod_title` alanına yönlendirin. ## 7. Satın Alma Düğmesini Ekle \{#add-the-purchase-button\} Satın alma düğmesi, kullanıcının seçtiği ürün için uygulama içi satın alma işlemini başlatır. Etiketinde seçili ürünün fiyatı gösterildiğinden, kullanıcı planlar arasında geçiş yaptıkça otomatik olarak güncellenir. Satın Alma eylemi hakkında daha fazla bilgi için bkz. [Eylemler — Satın Alma](onboarding-actions#purchase). Satın alma düğmesini eklemek ve yapılandırmak için: 1. **+** > **Buttons** seçeneğine tıklayın ve bir buton ön ayarı seçin. 2. Butonu seçtikten sonra **Design** sekmesini açın ve imleci **Content** alanına getirin. Değişken simgesine Variable icon tıklayın, `products.selectedProduct` öğesini, ardından `prod_price` özniteliğini seçin — tam değişken `products.selectedProduct.prod_price` olarak çözümlenir. Etiketin geri kalanıyla çevreleyerek tamamlayın — örneğin, `Subscribe for {prod_price}`. 3. **Interactions** sekmesine geçin ve **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın. 4. **Action** değerini **Purchase**, **Product** değerini `products.selectedProduct` olarak ayarlayın. ## 8. Alt bölüm bağlantılarını ekleyin \{#add-the-footer-links\} Kullanım koşulları, gizlilik politikası ve satın almaları geri yükleme seçenekleri ana içeriğin altında yer alır. Alt bölüm bağlantılarını eklemek için: 1. **+** > **Buttons** > **Links** seçeneğine tıklayın. Bu adım, katman ağacının sonuna Restore Purchases, Terms of Use ve Privacy Policy içeren bir satır ekler. 2. **Layers** panelinde **Terms of Use** düğmesini seçin. **Interactions** sekmesini açın ve koşullar URL'nizi **Open URL** alanına yapıştırın. 3. Gizlilik URL'niz için **Privacy Policy** düğmesiyle aynı adımı tekrarlayın. 4. **Restore Purchases** bağlantısını olduğu gibi bırakın. Bu bağlantının eylemi önceden yapılandırılmıştır. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). --- # File: show-offer-on-close --- --- title: "Kullanıcılar kapat'a dokunduğunda teklif göster" description: "Son bir teklif göstermek için kullanıcılar paywall'dan ayrılmadan önce ilk kapat dokunuşunu yakala." --- Bir kullanıcı kapat düğmesine dokunduğunda, ödeme yapmadan ayrılmak üzeredir. Bu tarif ilk kapat dokunuşunu yakalar: paywall'ı kapatmak yerine son bir teklif overlay'i gösterir. Kullanıcı teklifi kapattığında, kapat düğmesi normal şekilde çalışır ve flow'u kapatır. Bu mantık bir özel Boolean değişkeni ve bir koşullu eylem gerektirir: - `close_tapped` başlangıçta `False` olarak ayarlanır. - İlk kapat dokunuşu teklif overlay'ini gösterir ve `close_tapped` değerini `True` olarak ayarlar. - Sonraki her kapat dokunuşu flow'u kapatır. ## Başlamadan önce \{#before-you-start\} - Kapatma düğmesi içeren bir paywall ekranı oluşturun — örneğin, [Temel paywall ekranı oluşturma](basic-paywall-screen) adımlarını takip edin. - Overlay'de tanıtmak için [teklif](offers) içeren bir [ürün](create-product) oluşturun. ## 1. Değişkeni oluşturun \{#create-the-variable\} Özel değişkenler hakkında daha fazla bilgi için [Değişkenler](onboarding-variables#custom-variables) sayfasına bakın. 1. Sol panelde **{ }** simgesine tıklayarak **Variables** bölümünü açın. 2. **Custom** sekmesinde **+** düğmesine tıklayın. 3. Değişkeni `close_tapped` olarak adlandırın ve **Value Type** alanını **Boolean** olarak ayarlayın. **Initial Value** değerini **False** olarak bırakın. 4. **Create variable** düğmesine tıklayın. ## 2. Teklif katmanını oluşturun \{#build-the-offer-overlay\} Katman, cihaz ekranına sabitlenen ve paywallın üzerine oturan bir kapsayıcıdır. Görünür şekilde oluşturun — gizli öğeler düzenlenemez; içerik yerleştikten sonra 4. adımda gizleyeceksiniz. 1. **+** > **Layout** > **Vertical Container** seçeneğine tıklayın. 2. Kapsayıcı seçiliyken **Design** sekmesini açın ve **Position** değerini **Fixed** olarak ayarlayın. Yatay hizalamayı **Left & Right**, dikey hizalamayı **Top** olarak belirleyin. Dikey ortalama seçeneği olmadığından, overlay'i ekranın ortasına taşımak için bir üst kenar boşluğu girin (örneğin `300`). 3. **Fill** bölümünde bir arka plan belirleyin — düz renk veya görsel olabilir. Kapsayıcı varsayılan olarak şeffaf olduğundan, dolgu eklemezseniz overlay'in altındaki paywall görünür olmaya devam eder. 4. Teklif içeriğini ekleyin. **Layers** panelinde kapsayıcı seçiliyken **+** > **Text** > **H2** seçeneğine tıklayın. İndirimli fiyatı göstermek için **Content** alanına `offer_price` gibi [teklif değişkenleri](onboarding-variables#product-variables) ekleyin. 5. **+** > **Products** seçeneğine tıklayın, bir düzen şablonu seçin ve overlay'in içine sürükleyin. Tuvaldeki ürün kartını seçin, ardından **Design** sekmesinden ürünü ve teklifi belirleyin. 6. **+** > **Buttons** seçeneğine tıklayın, bir buton şablonu seçin ve overlay'in içine sürükleyin. **Interactions** sekmesinde **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın, ardından **Action** değerini **Purchase**, **Product** değerini ise teklif ürününüz olarak ayarlayın. ## 3. Overlay'e kapatma düğmesi ekle \{#add-the-dismiss-button-to-the-overlay\} Overlay'in kendi kapatma düğmesine ihtiyacı var. Bu düğmenin eylemi flow'u kapatmamalı, yalnızca overlay'i gizlemelidir. 1. Overlay seçiliyken **+** > **Buttons** > **Close flow** seçeneğine tıklayın. 2. Düğme seçiliyken **Interactions** sekmesini açın. Hazır ayar, önceden yapılandırılmış bir **Close Flow** eylemiyle gelir. Eyleme tıklayın ve türünü **Hide element** olarak değiştirin. Hedefi overlay container olarak ayarlayın. :::important Overlay'in kapatma düğmesindeki önceden yapılandırılmış **Close Flow** eylemini kaldırmayı unutmayın — bu eylem, overlay'i gizlemek yerine tüm flow'u kapatır. ::: ## 4. Katmanı gizle \{#hide-the-overlay\} Katman, ilk kapatma dokunuşuna kadar görünmez kalmalıdır. **Layers** panelinde katman kapsayıcısını seçin ve durumunu **Hide** Hide olarak ayarlayın. Katman, katman ağacında kalmaya devam eder ancak canvas üzerinde artık görüntülenmez. ## 5. Kapat düğmesini ayarlayın \{#set-up-the-close-button\} Kapat düğmesinin varsayılan işlemini, `close_tapped` üzerinde dallanan koşullu bir işlemle değiştirin. Koşullu işlemler hakkında daha fazla bilgi için bkz. [İşlemler — Koşullu işlemler](onboarding-actions#conditional-actions). 1. Paywallın kapat düğmesini seçin — ekrandaki düğmeyi, katmanın kapatma düğmesini değil. 2. **Interactions** sekmesini açın, önceden yapılandırılmış **Close Flow** aksiyonuna tıklayın ve türünü **Conditional Action** olarak değiştirin. 3. **if** bloğunda **Add condition**'a tıklayın ve şunu ayarlayın: `close_tapped` **Equals** **False**. 4. **then** bloğuna iki aksiyon ekleyin: - **Set Variable**: `close_tapped` değerini **True** olarak ayarlayın. - **Show element**: Hedef olarak teklif katmanını ayarlayın. 5. **else** bloğuna bir **Close Flow** eylemi ekleyin. Artık ilk kapatma dokunuşu teklifi gösteriyor. Kullanıcı teklifi kapattıktan sonra, tekrar kapatmaya dokunmak **else** dalıyla eşleşerek flow'u kapatıyor. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). --- # File: strikethrough-price --- --- title: "İndirim rozeti ile üzeri çizili fiyat gösterme" description: "Yıllık planın aylık fiyatının yanında, aylık planın fiyatını üzeri çizili olarak göstererek indirimi tek bakışta fark edilir hale getirin." --- Gerçek fiyatın yanındaki üzeri çizili fiyat, indirimi tek bakışta görünür kılar. Bu rehber, yıllık ürün kartını; aylık plandaki abonelik maliyetini üzeri çizili biçimde, yıllık planın etkin aylık fiyatının yanında ve üstünde bir indirim rozetiyle gösterecek şekilde yeniden düzenler. Üstü çizili biçimlendirme, metnin tamamına uygulanır; bir değişkeni büyük bir metin öğesinin içinde çizemezsiniz. Bu yüzden üstü çizili fiyat, indirimli fiyatla yan yana, yatay bir kapsayıcı içinde kendi metin öğesinde yer alır. :::tip Eğer aynı ürün için şişirilmiş bir "önceki" fiyat yeterliyse — örneğin, üzeri çizili olarak mevcut fiyatın iki katı — bunun yerine hazır [Eski Fiyat öğesini](onboarding-text#add-an-old-price) ekleyebilirsiniz. Bu tarif, üzeri çizili fiyatın başka bir ürünün gerçek fiyatı olduğu durumu kapsar. ::: ## Başlamadan önce \{#before-you-start\} - Ürünler içeren bir paywall ekranı oluşturun — örneğin [Temel bir paywall ekranı oluşturma](basic-paywall-screen) adımlarını takip edebilirsiniz. Bu örnekte paywall'ın yıllık ve aylık bir ürün sunduğu varsayılmaktadır. ## 1. Fiyat satırlarını üst üste koy \{#stack-the-price-rows\} Yıllık kart, tek bir fiyat satırıyla başlar — yıllık ürünün `prod_price` değişkeni ve ardından gelen `/year` ifadesi, örneğin `$29.99/year` şeklinde görüntülenir. Bunun üstüne aylık fiyatlandırma için ikinci bir satır ekle. 1. **Layers** panelinde, yıllık ürün kartının içindeki fiyat metnini seçin. Metin zaten kartın dikey container'ında yer aldığından, kopya onun altına yerleşecek. 2. Katmandaki üç nokta menüsüne Context menu tıklayın ve **Duplicate**'i seçin. Kopya, orijinalin altında görünür. Bir sonraki adımda, üstteki metin aylık fiyat satırı olacak; alttaki ise yıllık fiyatı koruyacak. ## 2. Aylık satırını iki fiyata bölün \{#2-split-the-monthly-row-into-two-prices\} Aylık satırı iki metin öğesi içerir: üzeri çizili aylık plan fiyatı ve yıllık planın aylık başına fiyatı. :::important Değişken seçici yalnızca bir flow ekranında mevcut olan ürünlerin fiyatlarını sunar. Flow'da bulunmayan bir ürüne başvurmak için boş bir ekran oluşturun, oraya bir **Products** öğesi ekleyin ve ürünü buna atayın. Hiçbir gezinme eyleminin o ekrana yönlendirmediğinden emin olun. ::: 1. Üstteki metin öğesini seçin, üç nokta menüsüne tıklayın ve **Wrap** > **Wrap in Horizontal Container** seçeneğini belirleyin. 2. Yeni container içindeki metin katmanının üç nokta menüsüne tıklayın ve **Duplicate** seçeneğini belirleyin. 3. İlk metin öğesini seçin ve **Content** alanını temizleyin. Değişken simgesine Variable icon tıklayın, aylık ürünü seçin, ardından `prod_price_per_month` özniteliğini seçin. Değişkenin ardına `/month` yazın. 4. **Design** sekmesinde, **Typography** altında, **Decoration** değerini **Strikethrough** Strikethrough olarak ayarlayın (bkz. [Stiller ve görünüm — Decoration](builder-styling#decoration)). 5. İkinci metin öğesini seçin ve içeriğini aynı şekilde değiştirin; ancak bu sefer yıllık ürünün `prod_price_per_month` özniteliğini seçin. Değişkenin ardına `/month` yazın. ## 3. Yıllık fiyatı daha az belirgin yapın \{#tone-down-the-yearly-price\} Kopyalanan aylık fiyatlar, orijinal fiyat stilini miras aldığından şu anda üç fiyat da aynı boyut ve kalınlığı paylaşıyor. Yıllık fiyatı daha ince bir görünüme kavuşturun; böylece aylık satır öne çıkar. 1. Tuvalde, alt metin öğesini seçin — yıllık fiyat. 2. Öğenin üzerindeki araç çubuğunda metin stili açılır menüsünü açın ve daha ince bir stil seçin — örneğin **Caption**. Ya da **Design** sekmesinde **Typography** altından farklı bir stil belirleyebilirsiniz. ## 4. İndirim rozetini ekle \{#add-the-discount-badge\} Rozet, fiyatların yanında tasarrufu vurgular. 1. **+** > **Badge** seçeneğine tıkla. 2. **Layers** panelinde rozeti yıllık ürünün içine, fiyatların bulunduğu dikey container ile radyo düğmesi arasına sürükle. 3. Rozetin metin katmanını seç ve **Content** alanını düzenle — örneğin `%75 Tasarruf Et`. İndirim yüzdesi için bir değişken bulunmuyor — hesaplamayı kendi fiyatlarından yapıp sabit metin olarak gir. Artık yıllık kart, fiyatını aylık plana göre konumlandırıyor: üstü çizili aylık fiyat, yıllık planın aylık bazda efektif fiyatı ve indirim rozeti tek bir satırda yer alıyor; tam yıllık fiyat ise bunların altında gösteriliyor. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). --- # File: onboarding-flow-tutorial --- --- title: "Kişiselleştirilmiş bir onboarding flow'u oluşturun" description: "Çok ekranlı bir onboarding flow'u oluşturmanın tüm sürecini — ekranlar, içerik, navigasyon ve koşullu dallanma — gerçek bir örnek üzerinden adım adım inceleyin." --- Flow Builder'da çok ekranlı bir flow, gezinti eylemleriyle birbirine bağlanan ekranların bir dizisidir. Flow düz devam edebilir ya da daha önceki bir ekranda toplanan kullanıcı girdisine bağlı olarak dallanabilir. Bu eğitim, dört ekranlı bir onboarding flow'unu örnek alarak tüm süreci adım adım ele alıyor: ekran oluşturma, içerik hazırlama, gezintiyi bağlama ve koşullu dallanma ekleme. Örnekte şunlar kullanılmaktadır: - Kullanıcının adını kişiselleştirme için değişken olarak sunan bir **isim girişi**. - Cevabına göre kullanıcının hangi ekrana yönlendirileceğini belirleyen bir **tek seçimli quiz**. - Her kitle segmenti için özelleştirilmiş içerikle **iki dallanma yolu**. - Son ekran olarak bir **paywall**. Aynı yapı, kullanıcı girdisine göre içerik kişiselleştiren her flow için geçerlidir. Video formatını mı tercih ediyorsunuz? Bu hızlı başlangıç eğitimi aynı süreci baştan sona ele alıyor: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/aa-m459VIuY?si=zN_Co6B6qB88UPZP" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Başlamadan önce \{#before-you-start\} - Adapty Kontrol Paneli'nde [ürün oluşturun](create-product). Örnek flow, biri Yıllık diğeri Aylık olmak üzere iki abonelik kullanır. - [Adapty'yi App Store ve Google Play'e bağlayın](integrate-payments). ## 1. Yeniden kullanılabilir stiller oluşturun \{#set-up-reusable-styles\} Yeniden kullanılabilir stiller, tüm ekranlarda tutarlı tipografi ve renkleri tek tıklamayla uygulamanıza olanak tanır. Renk stilleri açık ve koyu tema varyantı içerir; bu sayede flow her iki temayı da otomatik olarak destekler. Tüm talimatlar için bkz. [Stiller ve görünüm — Yeniden kullanılabilir stiller](builder-styling#reusable-styles). Stilleri ayarlamak için: 1. Sol panelde **Styles** Styles panelini açın. 2. **Colors** sekmesinde **Plus Create style**'a tıklayın ve tekrar kullanacağınız renkleri ekleyin. Her renk için bir Light değeri seçin, Dark sekmesine geçin ve bir Dark değeri belirleyin. 3. **Text** sekmesinde mevcut bir stile tıklayarak yazı tipini, kalınlığını ve boyutunu düzenleyin ya da özel ön ayarlar eklemek için **Plus Create style**'a tıklayın. ## 2. Ekranları oluşturun \{#2-create-the-screens\} Flow, bir dizi ekrandan oluşur. İlk ekranı paylaşılan temel yapıyla — düzen, arka plan ve güvenli alan — yapılandırın, ardından geri kalanı için bu ekranı çoğaltın. Böylece her ekran aynı temeli paylaşır ve bunu yalnızca bir kez ayarlamanız gerekir. Ekranları yönetme hakkında daha fazla bilgi için bkz. [Ekranlar ve Katmanlar — Ekranları yönetme](paywall-layout-and-products#manage-screens). Ekranları ayarlamak için: 1. İlk ekranın ekran ayarlarını açmak için tuvalin boş bir alanına tıklayın. 2. **System UI** altında, arka planların ve kenara hizalı öğelerin ekran kenarlarına kadar uzanabilmesi için **Safe area** seçeneğini devre dışı bırakın. 3. **Fill** altında, bir arka plan türü seçin ve yapılandırın — örneğin, flow'un her ekranının arkasında yer alan bir **Image** Image. 4. **Layout** altında, yönü **Vertical** Vertical olarak ayarlayın ve tasarımınıza uygun bir dağılım seçin. 5. Sol panelin **Screens** bölümünde, ilk ekranın üç nokta menüsüne Bağlam menüsü tıklayın ve **Duplicate** seçeneğini belirleyin. Toplamda dört ekrana ulaşana kadar tekrarlayın — ikinci dallanma yolu, birincisi kopyalanarak daha sonra eklenecektir. 6. Her ekranı rolüyle eşleşecek şekilde yeniden adlandırın — örneğimizde: `Welcome`, `Quiz`, `Rock path` ve `Paywall`. ## 3. Giriş ekranını oluşturun \{#build-the-introduction-screen\} İlk ekran genellikle tonu belirler — bir başlık, özellik listesi ve flow'un geri kalanını açan bir harekete geçirici mesaj. Örneğimizde bu, Karşılama ekranıdır. **Screens** panelinde **Welcome** ekranına tıklayın, ardından öğeleri ekleyin: 1. Ana görseli ekleyin. **+** > **Media** > **Image** seçeneğine tıklayın, görselinizi yükleyin ve gerekirse kenar boşluklarını ayarlayın. 2. Başlık ekleyin: **+** > **Text** seçeneğine tıklayın, kayıtlı metin stillerinizden bir başlık stili belirleyin ve **Content** alanını düzenleyin. 3. Özellik listesini ekleyin. **+** > **List** > **Icon Cards** seçeneğine tıklayın, ardından her karttaki ikonu ve etiketi düzenleyin. 4. Alt kısma birincil bir gezinti düğmesi ekleyin. Bu düğmeye gezinti adımında bir eylem bağlanacak. ## 4. Giriş ve sınav ekranını oluşturun \{#build-the-input-and-quiz-screen\} İkinci ekran, kullanıcıdan bilgi toplar. Örneğimizde bir isim ve kullanıcının sonraki hangi yolu göreceğini belirleyen tek seçimli bir soru sorar. Giriş ve sınavlar hakkında daha fazla bilgi için [Giriş ve formlar](builder-inputs-and-forms) ve [Anket ve sınavlar](onboarding-quizzes) sayfalarına bakın. **Screens** panelinde **Quiz** ekranına tıklayın, ardından öğeleri ekleyin. Ekrandaki her grup — giriş, soru + giriş alanı, soru + sınav — ilgili öğeler görsel olarak bir arada kalacak şekilde kendi Dikey Kapsayıcısı içinde yer alır. 1. Giriş başlığını ve metnini ekleyin. Başlık için **+** > **Text** > **H1**, açıklama metni için **+** > **Text** > **Body** seçin. 2. Girişi gruplayın. **+** > **Layout** > **Vertical Container** seçin, yeni container'ı katman ağacının en üstüne sürükleyin, ardından H1 ve metni içine sürükleyin. 3. İlk soru ve girişi ekleyin. Soru başlığı için **+** > **Text**, alan için ise **+** > **Inputs** > **Text** seçeneğine tıklayın. 4. **Design** sekmesinde girişin **Element ID**'sini ayarlayın — örneğimizde `name`. Bu, değeri diğer ekranların başvurabileceği bir değişken olarak kullanıma sunar. 5. Başlık ve input'u, intro ile aynı şekilde bir Vertical Container içinde gruplayın. 6. İkinci soruyu ve quiz'i ekleyin. Başlık için **+** > **Text**, ardından **+** > **Quiz** seçeneğine tıklayın ve Icon Options gibi bir düzen şablonu seçin. Seçenekleri yapılandırın — örneğimizde `Rock` ve `Hip hop`. 7. Başlık ve quiz'i aynı şekilde bir Vertical Container içinde gruplayın. 8. Seçenek ID'lerini ayarlayın. Her quiz seçeneğini seçin, **Interactions** sekmesini açın ve **Element ID**'sini belirleyin. Bu ID'ler, ilerleyen adımlarda koşullu navigasyonda kullanılacaktır. 9. Quizi tek seçimli yapın: tuvalin boş bir alanına tıklayarak **Screen settings** bölümünü açın, **Selectable Groups** kısmına kaydırın, quiz grubunun adına tıklayın ve türü **Single choice** olarak ayarlayın. 10. Alta bir birincil düğme ekleyin — bu, dallanmayı tetikleyen İleri düğmesidir. ## 5. İlk dallanma yolunu oluşturun \{#build-the-first-branching-path\} Her yol ekranı, bir kitle segmentine özel içerik sunar. Örneğimizde, Rock yolu rock odaklı içerikler barındırır: çalma listeleri, sanatçılar ve öneriler. Değişkenler hakkında daha fazla bilgi için [Değişkenler](onboarding-variables) sayfasına bakın. Ekranı oluşturmak için: 1. **Screens** panelinde **Rock path** ekranına tıklayın. 2. Bir başlık ekleyin. **Content** alanına imleci yerleştirin ve kişiselleştirmenin görüneceği yere gelin, ardından değişken simgesine Variable icon tıklayın ve **Elements** sekmesini açın. Girdinin bulunduğu ekranı seçin — örneğimizde **Quiz** — ardından girdinin değer değişkenini seçin. Seçici bunu `<elementId>.value` olarak çözümler — örneğimizde `name.value`. Çalışma zamanında başlık, kullanıcının yazdığı içerikle güncellenir. 3. Gövde metnini, bu yol için kitle segmentine uygun ek metin öğeleri olarak ekleyin. 4. Alta bir birincil düğme ekleyin. ## 6. İkinci dallanma yolunu oluşturun \{#build-the-second-branching-path\} Yol ekranları genellikle aynı düzeni paylaşır — yalnızca metinler değişir. İlk yol ekranını çoğaltın ve içeriği güncelleyin. Çoğaltmak ve güncellemek için: 1. **Screens** panelinde ilk yol ekranını seçin ve ⌘D / Ctrl+D tuşlarına basarak çoğaltın. Kopya, ekran listesinin sonunda görünür. 2. Kopyayı yeniden adlandırın — örneğimizde `Hip hop path` — ve ekran listesinde doğru konuma sürükleyin; böylece kopyalandığı ekranın yanında yer alır. 3. Diğer kitle segmenti için gövde metnini güncelleyin. Kişiselleştirilmiş başlık çalışmaya devam eder — değişken aktarılır. ## 7. Paywall'ı oluşturun \{#build-the-paywall\} Son ekran, kullanıcının abone olabileceği paywall'dır. Paywall mekaniklerine ilişkin daha kapsamlı bir rehber için [Temel bir paywall ekranı oluşturma](basic-paywall-screen) bölümüne bakın. Aşağıdaki versiyon bu rehberi özetlemektedir. **Screens** panelinde **Paywall** ekranına tıklayın, ardından şu öğeleri ekleyin: 1. Üste bir **Horizontal Container** ekleyin ve içine bir **Close** butonu yerleştirin. Close ön ayarı önceden yapılandırılmış olarak gelir. 2. Ana görseli, başlığı (yol ekranlarındakiyle aynı kişiselleştirme değişkenini kullanarak) ve destekleyici metin olarak bir alt başlık ekleyin. 3. Ürünleri ekleyin: **+** > **Products** düğmesine tıklayın ve **Vertical List**'i seçin. **Design** sekmesindeki açılır menüden her karta bir ürün atayın. 4. Varsayılan ürünün kartına tıklayın ve ekran yüklendiğinde otomatik seçili olması için **Set as default product** seçeneğini etkinleştirin. 5. Satın alma düğmesini ekleyin. **+** > **Buttons** seçeneğine tıklayın ve bir önayar seçin. **Interactions** sekmesinde **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın ve **Action**'ı **Purchase** olarak, **Product**'ı ise `products.selectedProduct` olarak ayarlayın. 6. Ekrana **Button** > **Links** şablonunu ekleyin. Bu şablon üç alt bağlantı içerir: Restore Purchases, Terms of Use ve Privacy Policy. Geri Yükleme bağlantısı önceden yapılandırılmıştır. Diğer bağlantıları yapılandırmak için düğme öğesini seçin, **Interactions** sekmesini açın ve **Open URL** eylemi için hedefi belirleyin. ## 8. Ekranlar arasında navigasyonu bağlayın \{#wire-navigation-between-the-screens\} Ekranlar birbirine otomatik olarak bağlanmaz. Her ekranın birincil düğmesini bir sonraki ekrana bağlamak için **On tap** tetikleyicilerini ve **Navigate to** eylemlerini kullanın. Kullanıcı girdisine göre dallanma yapan bir ekran, bunun yerine **Conditional action** kullanır. Navigasyon ve koşullu eylemler hakkında daha fazla bilgi için bkz. [Navigasyon ve etkileşim](onboarding-navigation-branching) ve [Eylemler — Koşullu eylemler](onboarding-actions#conditional-actions). Örnek flow için navigasyonu bağlamak üzere: 1. **Giriş ekranından statik navigasyon.** Hoş Geldiniz ekranını açın, birincil düğmeyi seçin ve **Interactions** sekmesine geçin. **Add trigger** > **On tap** > **Add action** seçeneğine tıklayın, **Action** alanını **Navigate to** olarak ayarlayın ve bir sonraki ekranı seçin — örneğimizde Quiz ekranı. 2. **Testen koşullu navigasyon.** Quiz ekranını açın, Next butonunu seçin ve bir **Conditional action** içeren **On tap** tetikleyicisi ekleyin. IF/ELSE kuralını şu şekilde ayarlayın: - Değişken seçicisinde **Elements** sekmesini açın, **Quiz** ekranını seçin ve `quiz.selectedOptionId`'yi seçin. - **Equals** operatörünü kullanın ve seçeneklerden birinin ID'siyle karşılaştırın — örneğimizde Rock seçeneği. - **IF** koşulu eşleşirse, **Navigate to** tetikleyin ve birinci yol ekranını seçin. - **ELSE** durumunda, **Navigate to** tetikleyin ve ikinci yol ekranını seçin. 3. **Her dallanma yolundan paywalla statik navigasyon.** 1. adımdaki deseni, hedef olarak paywall belirleyerek her yol ekranında tekrarlayın. ## Sonraki adımlar \{#next-steps\} - [Flow'unuzu kaydedin ve yayınlayın](builder-save-publish). - Kullanıcılara göstermeye başlamak için [flow'u bir placement'a ekleyin](create-placement). - Kitleye özel flow'lar için (flow içi dallanma yerine) kitle segmentleri oluşturun ve Placement sayfasında farklı flow'lar atayın. :::link Flow oluşturma hakkında daha fazla bilgi edinmek ister misiniz? [YouTube oynatma listemizde](https://www.youtube.com/playlist?list=PLMksWqaZiWtM) adım adım video eğitimlerini izleyin. ::: --- # File: migrate-to-flows --- --- title: "Flow'lara geçiş" description: "Ayrı onboarding ve paywallınızı tek bir Adapty flow'una taşıyın — neler değişiyor ve eski uygulama sürümlerindeki kullanıcıları etkilemeden nasıl yayına alabilirsiniz." --- Adapty'de bir *flow*, onboarding ve paywallı tek bir placement arkasında tek bir varlık olarak birleştirir. Flow, bugün ayrı ayrı oluşturup sunduğunuz onboarding ve paywallın yerini alır. Bu kılavuz, flow'lara geçişte nelerin değiştiğini ve eski uygulama sürümlerindeki kullanıcıları etkilemeden bu geçişi nasıl yapacağınızı açıklar. :::important Flow'lar şu anda iOS, Android, React Native, Flutter ve Capacitor SDK v4 ve üzeri sürümlerde desteklenmektedir. Diğer platformlar ve framework'ler için destek yakında eklenecektir. ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/8Cby6lVGI0o?si=rYA1HtdayyF1ffWd" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Flow'lar ile onboarding'ler ve paywall'lar \{#flows-vs-onboardings-and-paywalls\} Ayrı onboarding'ler ve paywall'larla iki ayrı builder ve iki ayrı placement yönetirsiniz. Kullanıcıyı onboarding'den paywall'a geçirmek için de kendi kodunuzu yazmanız gerekir. Bir flow ise her ikisinin yerini alır; giriş ekranları, bir quiz ve satın alma ekranı tek bir editörde oluşturulur ve tek bir placement üzerinden sunulur. Aşağıdaki tablo her seçeneğin size neler sunduğunu karşılaştırır: | | Flow | Paywall Builder paywall | Onboarding | |---|---|---|---| | Çoklu ekran | Evet | Hayır — tek ekran | Evet | | Render | Native | Native | WebView | | Ürünler ve placement | Tek placement; ürünleri doğrudan flow'a eklersiniz | Tek placement; ürünleri doğrudan paywall'a eklersiniz | Tek placement, ancak kendine ait ürün yok — satış yapmak için ayrı bir paywall oluşturup kendi placement'ından sunmanız gerekir | ## Taşımalı mısınız? \{#should-you-migrate\} Mevcut onboarding'leriniz ve paywall'larınız çalışmaya devam eder; Adapty bunları desteklemeyi sürdürmektedir. Ancak yeni özellikler artık bağımsız onboarding ve paywall builder'lar yerine flow'lara eklenmektedir. **Uzun vadeli düşünüyorsanız, flow'lar daha sağlam bir temeldir** — yayın takviminize uygun bir zamanda geçişi yapın. ## Nasıl taşınır \{#how-to-migrate\} Taşıma işlemi dört adımdan oluşur. Çabanın büyük kısmı tek seferlik bir SDK yükseltmesidir — flow oluşturma ve önizleme kodsuz yapılır. 1. **[Flow'unuzu oluşturun](#build-your-flow)**: Flow'u no-code editörde oluşturun; geliştirici gerekmez. 2. **[Cihazda önizleyin](#preview-on-device)**: Flow'u Adapty mobil uygulaması üzerinden gerçek bir cihazda kontrol edin; uygulama derlemesi gerekmez. 3. **[Flow'unuz için yeni bir placement oluşturun](#create-a-new-placement-for-your-flow)**: Kendine özgü bir ID'ye sahip yeni bir flow placement'ı oluşturun ve mevcut placement'larınızla nasıl bir arada var olacağına karar verin. 4. **[SDK'yı güncelleyin](#update-the-sdk)**: iOS, Android, React Native veya Capacitor SDK v4'e yükseltin, flow'u placement'ından alın ve bir sandbox satın almasını doğrulayın. Bu, temel geliştirici görevidir. ### Flow'unuzu oluşturun \{#build-your-flow\} **Flows** sayfasında **Create flow** düğmesine tıklayarak onboarding ve paywall'ınızı tek bir deneyim olarak oluşturmaya başlayın. Builder hakkında daha fazla bilgi edinmek için: - **[Flows dokümantasyonu](adapty-flow-builder)**: Builder'ı ve neler oluşturabileceğinizi adım adım anlatır. - **[Yaygın flow şablonları](flow-builder-recipes)**: En sık kullanılan ekranlar için adım adım kılavuzlar. - **AI'ya sorun**: Takıldığınızda herhangi bir dokümantasyon sayfasındaki sohbet aracını kullanın. :::note Hazır bir flow şablonundan flow oluşturma veya yapay zeka ile oluşturma henüz mevcut değil — her ikisi de yakında geliyor. Şimdilik her yeni flow, ihtiyaçlarınıza göre düzenleyip stillendirebileceğiniz birkaç yaygın kullanılan ekranla başlar. ::: ### Cihazda önizleme \{#preview-on-device\} Flow'u uygulamaya dokunmadan gerçek bir cihazda önizleyebilirsiniz. [Adapty uygulamasını](https://apps.apple.com/us/app/adapty/id6739359219) App Store'dan indirin. Ardından flow builder'da **Test on device** seçeneğine tıklayın, bir yerel ayar seçin ve QR kodu cihazınızla tarayın. Bu işlem gerçek ekranları, dallanmaları, metinleri ve tasarımı gösterir. :::note Önizleme modunda Adapty, mağazalardaki ürünlerinize erişemez; bu nedenle önizlemede gösterilen fiyatlar gerçek değildir. Gerçek satın almalar daha sonra, sandbox hesabıyla v4 build'inde doğrulanır — bkz. [SDK'yı güncelleme](#update-the-sdk). ::: ### Flow'unuz için yeni bir placement oluşturun \{#create-a-new-placement-for-your-flow\} Bir placement yalnızca tek bir içerik türüne hizmet eder — flow, paywall veya onboarding. Mevcut bir onboarding ya da paywall placement'ını flow placement'ına dönüştüremezsiniz (bkz. [placement türleri](create-placement)). Flow için ayrı, yeni bir placement oluşturmanız gerekir. **Yeni flow placement'ına tamamen yeni ve benzersiz bir placement ID verin.** Bu ID, mevcut herhangi bir paywall veya onboarding placement'ının ID'siyle aynı olamaz ya da onu yeniden kullanamazsınız. :::warning Geçiş süresince eski placement'larınızı aktif tutun Eski uygulama sürümlerindeki kullanıcılar, onboarding ve paywall placement ID'lerinizi uygulamaya derlenmiş şekilde kullanmaya devam eder. Bu kullanıcılar onboarding ve paywall metodlarını çağırmayı sürdürür ve güncelleme yapana kadar mevcut onboarding ile paywall'ı görür. Eski placement'ları yalnızca SDK v4 benimseme oranınız yeterince yükseldiğinde devre dışı bırakın. ::: SDK v4'te her location'ı aynı anda flow'a taşımak zorunda değilsiniz. `getFlow` metodu hem flow placement'lardan hem de paywall placement'lardan veri çektiği için uygulamanız her yerde aynı metodu çağırır. Paywall Builder paywall'larını istediğiniz placement'larda bırakın, geri kalanlar için flow kullanın. Geçiş sürecinde her placement türü kendi metriklerini takip eder. Hem eski hem yeni uygulama sürümleri aktifken, verileriniz iki placement grubu arasında bölünür. Eski onboarding ve paywall placement'ları daha eski sürümleri; yeni flow placement'ı ise SDK v4+'ı kapsar. Bunları ayrı kohortlar olarak karşılaştırın ve kullanıcılar güncelleme yaptıkça flow placement'ının payının büyümesini bekleyin. Flow varyantları üzerinde bir flow placement'ta [Normal A/B testi](ab-tests) çalıştırarak A/B testine devam edebilirsiniz. Placement'lar arası A/B testleri şu an yalnızca paywall'lar için kullanılabilir, dolayısıyla flow placement'lar arasında henüz çalıştıramazsınız. Yeni bir flow'u eski paywall'ınızla karşılaştırmak, tek bir test değil kohort karşılaştırmasıdır — bunlar farklı placement türlerinde yer alır. ### SDK'yı Güncelleyin \{#update-the-sdk\} Flow placement'ınız hazır olduğunda, uygulamayı ona yönlendirin. Flow'lar yalnızca Adapty SDK v4 ve sonrasında çalışır. SDK'yı güncelleyin ve yeni placement'ınızdan flow'u `getFlow` ile çekin. Belirli yükseltme adımları için platformunuza ait v4 migration rehberine bakın — [iOS](migration-to-ios-sdk-v4), [Android](migration-to-android-sdk-v4), [React Native](migration-to-react-native-sdk-v4) veya [Capacitor](migration-to-capacitor-sdk-v4). Flow'u bağladıktan sonra, diğer satın alma akışlarında yaptığınız gibi doğrulayın: bir cihazda veya simülatörde çalıştırın ve ürünlerin, satın almanın ve access level'ın doğru çalıştığını onaylamak için bir sandbox satın alması yapın ([iOS](ios-test) / [Android](testing-on-android)). :::note Kullanıcılar flow'ları yalnızca SDK v4+ ile oluşturulmuş uygulamayı yükledikten sonra görür. Eski uygulama sürümünü kullananlar mevcut onboarding ve paywall'larını görmeye devam eder; bu nedenle geçiş süresince eski placement'lar aktif kalmaya devam eder. Aynı durum flow'ları henüz desteklemeyen platformlar için de geçerlidir. ::: --- # File: paywall-layout-and-products --- --- title: Ekranlar ve katmanlar description: "Flow Builder'da ekranları ve her ekrandaki öğe hiyerarşisini yönetin." --- Bir flow, bir veya daha fazla ekrandan oluşur. Her ekran, kullanıcı yolculuğundaki tek bir adımı temsil eder; örneğin bir paywall, bir quiz veya ürün bilgisi içeren bir slayt olabilir. Her ekrandaki öğeler, bir katman hiyerarşisi şeklinde düzenlenir. Ekranlarınızı, katmanlarınızı ve öğelerinizi yönetmek için varsayılan **Screens and Layers** görünümünü açın. Bu görünüm, ekran sıranızı ve her ekranın katman yapısını gösterir. ## Ekranları yönetme \{#manage-screens\} Sol panelin üst bölümünde, flow'daki tüm ekranlar listelenir. Her giriş, numaralı bir etiket ve küçük resim önizlemesi gösterir. * **Ekran seçme**: Bir ekran girişine tıklayarak onu etkin hale getirin. Görsel editör seçili ekranı gösterir ve aşağıdaki Layers bölümü güncellenerek o ekranın katman hiyerarşisini görüntüler. * **Ekran ekleme**: Flow'a yeni boş bir ekran eklemek için Screens bölümünün üstündeki Plus düğmesine tıklayın. * **Şablon kütüphanesini açma**: [Flow şablonlarına](paywall-builder-templates) göz atmak ve uygulamak için Screens bölümünün üstündeki Templates düğmesine tıklayın. * **Ekranları yeniden sıralama**: Ekran girişlerini sürükleyip bırakarak flow'daki sıralarını değiştirin. :::important Flow'unuzda kullanılmayan boş ekranlar varsa yayınlayamazsınız. Yayınlamadan önce taslak ekranları silin. ::: ### Ekran eylemleri \{#screen-actions\} Bağlam menüsünü açmak için ekran girişindeki üç nokta simgesine Context tıklayın. | Eylem | Kısayol | Açıklama | |--------|----------|-------------| | **Animasyonu Oynat** | | Bu ekranda yapılandırılmış animasyonları önizle | | **Kopyala** | ⌘C / Ctrl+C | Ekranı panoya kopyala | | **Buraya yapıştır** | ⌘V / Ctrl+V | Daha önce kopyalanmış bir ekranı yapıştır | | **Çoğalt** | ⌘D / Ctrl+D | Ekranın bir kopyasını oluştur ve flow'a ekle | | **Yeniden adlandır** | | Ekranın görünen adını değiştir | | **Sil** | ⌘⌫ / Ctrl+Del | Ekranı flow'dan kaldır | :::tip Pano, flow'lar arasında kalıcıdır. Bir ekranı veya öğeyi bir flow'dan kopyalayın, başka bir flow açın ve yapıştırın. ::: :::warning Bir ekranı sildiğinizde, o ekranı hedef alan [Ekrana Gitme](onboarding-navigation-branching) eylemleri **hedefini kaybeder**, ancak eylem **silinmez**. Yeni bir hedef atayın ya da eylemi silin; aksi takdirde [flow'u önizleyemez veya yayınlayamazsınız](builder-save-publish#publish-a-flow). ::: ## Ekranlar arasında gezinme \{#navigate-between-screens\} :::link Ana makale: [Gezinme ve etkileşim](onboarding-navigation-branching) ::: Listedeki ekran sırası, gezinmeyi kendi başına belirlemez. Ekranları birbirine bağlamak için element etkileşimlerini kullanın: bir düğmeyi, kullanıcıyı başka bir ekrana yönlendirecek şekilde yapılandırın. ## Ekran ayarları \{#screen-settings\} Aktif ekranın özelliklerini ve ayarlarını görüntülemek için ekran önizlemesindeki boş bir alana tıklayın. Sağ panel, ekran ayarları görünümüne geçecektir. ### Sistem Arayüzü \{#system-ui\} Ekranın cihaz donanımıyla nasıl etkileşime girdiğini kontrol eder. * **Safe area**, içeriğin çentik ve sistem çubuklarıyla çakışmaması için dolgu ekler. * **Status bar**, sistem durum çubuğunu (saat, pil, sinyal simgeleri) gösterir veya gizler. ### İlerleme göstergesine ekranı dahil etme \{#include-screen-in-progress-indicator\} Flow'unuza bir [İlerleme Göstergesi](builder-loaders-and-progress-bars#progress-indicators) öğesi eklerseniz Adapty bunu her ekranda gösterir. Belirli bir ekranı ilerleme göstergesinden kaldırmak için **Include screen in progress indicator** seçeneğinin işaretini kaldırın. Karşılama ekranlarını, son paywallı veya ilerleme olarak kaydedilmesini istemediğiniz herhangi bir adımı temizlemek için bunu kullanın. ### Ekran düzeni \{#screen-layout\} :::link Tam makale: [Düzen ve konumlandırma](manage-paywall-ui-elements) ::: **Layout** bölümü, ekranın alt öğelerini nasıl dağıtacağını belirler. Bu özellikler herhangi bir kapsayıcı öğede kullanılabilir. * **Free**: Alt öğeler bağımsız olarak konumlandırılır. * **Vertical**: Öğeler, flexbox sütunu gibi yukarıdan aşağıya doğru sıralanır. * **Horizontal**: Öğeler, flexbox satırı gibi soldan sağa doğru sıralanır. Dikey ve yatay düzenler için aralık ve hizalamayı da yapılandırabilirsiniz. * **Alignment**: Öğenin çapraz eksen boyunca konumu. * **Gap**: Bitişik öğeler arasındaki boşluk. * **Distribution**: Alt öğeler arasındaki ve etrafındaki boşluğun dağılımı. #### RTL düzeni \{#rtl-layout\} Sağdan sola okunan yazı sistemleri için düzeni yansıtmak üzere **Mirror for RTL** onay kutusunu etkinleştirin. Yatay kapsayıcılardaki öğelerin sırası ters çevrilir. ### Ekran arka planı \{#screen-background\} :::link Ana makale: [Arka Planlar](paywall-head-picture) ::: **Fill**, [ekran arka planını](paywall-head-picture) düz renk, degrade, resim veya video olarak ayarlar. Arka plan, **Safe area** etkinleştirilmiş olsa bile çentik ve sistem çubukları arkasındaki alanlar dahil tüm cihaz görünüm alanını kaplar. #### Arka plan videosunu döngüye al \{#loop-background-video\} Arka plan videosunu sürekli döngüde oynatmak için **Loop** geçişini etkinleştirin. #### Özel bir medya kimliği atayın \{#assign-a-custom-media-id\} [Herhangi bir görsel veya videoda](custom-media) olduğu gibi, ekran arka planına SDK'nızda referans vermek için özel bir medya ID'si atayabilirsiniz. ### Ekran boşluğu \{#screen-spacing\} Ekranın her kenarı (üst, sağ, alt, sol) için dolgu miktarını ayarlar. ### Kaydırma \{#scroll\} Taşma davranışını kontrol eder. Ekran içeriği görüntü alanı yüksekliğini aştığında kaydırılabilir olması için **Vertical scroll** seçeneğini etkinleştirin. ### Seçilebilir gruplar \{#selectable-groups\} :::link Ana makale: [Seçilebilir öğeler ve gruplar](flow-selectable-elements) ::: **Selectable groups** bölümü, mevcut ekrandaki tüm seçilebilir grupları listeler; bunlar [quiz'ler](onboarding-quizzes), [ürünler](paywall-product-block), [sekmeler](builder-tabs), [deneme geçişleri](builder-toggles) veya herhangi bir [özel seçilebilir öğeden](flow-selectable-elements#make-an-element-selectable) oluşabilir. Bir grup girdisine tıklayarak onu yeniden adlandırabilir, türünü değiştirebilir, açığa çıkardığı değişkenleri görüntüleyebilir veya silebilirsiniz. ## Katmanları Yönetme \{#manage-layers\} Bir ekrandaki her öğe bir katman olarak temsil edilir. Katmanlar bölümü, aktif ekrandaki öğelerin sırasını gösterir. :::important Flow katmanları, grafik tasarım yazılımlarındaki katmanlar gibi üst üste gelmez. Bunun yerine, ekranın bağımsız bileşenlerini temsil ederler. Öğeler *yalnızca* [mutlak veya sabit konumlandırma](manage-paywall-ui-elements) kullandıklarında üst üste gelir. Yığılma sırası, katman ağacındaki konumlarına göre değil, `z-index` özelliğine göre belirlenir. ::: Ağaç yapısı, üst-alt ilişkilerini yansıtır. Herhangi bir üst katmanın yanındaki oka tıklayarak alt öğelerini genişletebilir veya daraltabilirsin. Katmanları doğrudan oluşturamazsın. [Öğe ekle](builder-elements) görünümü aracılığıyla eklediğin her öğe, ağaçta yeni bir katman olarak görünür. * **Katman seçme**: Bir katmanı seçmek için tıklayın. Görsel düzenleyici, tuvaldeki ilgili öğeyi vurgular ve sağ panel, o katmanın [tasarım](builder-styling) ve [etkileşim](onboarding-navigation-branching) özelliklerini gösterir. * **Katmanları yeniden sıralama**: Katmanları, üst kapsayıcı içindeki sıralarını değiştirmek için ağaç yapısında sürükleyip bırakın. Ağaçtaki sıra, ekrandaki görsel sırayla eşleşir. * **Katmanı gösterme veya gizleme**: Göz Eye simgesini ortaya çıkarmak için bir katmanın üzerine gelin. Katmanın görünürlüğünü açıp kapatmak için simgeye tıklayın. Gizlenen katmanlar ağaçta kalmaya devam eder, ancak görsel düzenleyicide veya cihazda görünmez. Çalışma zamanında görünürlüğü mantıkla kontrol etmek için [koşullu görünürlük](onboarding-element-visibility) özelliğini kullanın. * **Tüm katmanları daraltma**: Tüm ağacı katlamak için Layers bölümünün sağ üst köşesindeki daralt Collapse düğmesine tıklayın. ### Katman eylemleri \{#layer-actions\} Bağlam menüsünü açmak için üç nokta simgesine Context tıklayın. | Eylem | Kısayol | Açıklama | |--------|----------|-------------| | **Copy** | ⌘C / Ctrl+C | Katmanı panoya kopyalar | | **Paste here** | ⌘V / Ctrl+V | Daha önce kopyalanan katmanı alt öğe olarak yapıştırır | | **Duplicate** | ⌘D / Ctrl+D | Katmanın aynı kapsayıcı içinde bir kopyasını oluşturur | | **Rename** | | Katmanın görünen adını değiştirir. Varsayılan olarak katmanlar, içeriklerini veya bileşen türlerini ad olarak kullanır | | **Delete** | ⌘⌫ / Ctrl+Del | Katmanı ve tüm alt öğelerini kaldırır | | **Wrap** | | Katmanı yeni bir kapsayıcıya sarar: **Wrap in Horizontal Container** veya **Wrap in Vertical Container** | | **Unwrap / Ungroup** | | Sarmalayan kapsayıcıyı kaldırır ve alt öğelerini bir üst seviyeye taşır | | **Move up** | ↑ | Katmanı üst kapsayıcısında bir konum yukarı taşır | | **Move down** | ↓ | Katmanı üst kapsayıcısında bir konum aşağı taşır | --- # File: manage-paywall-ui-elements --- --- title: "Düzen ve konumlandırma" description: "Elemanları ekranda düzen, konum modu, boyutlandırma ve boşluklarla yerleştirin." --- Flow Builder, duyarlı düzenler oluşturur. Öğeleri tam koordinatlara sürüklemezsiniz; bunun yerine öğeleri, alt elemanlarını otomatik olarak düzenleyen **container**'ların içine yerleştirirsiniz. Container, öğelerin yönünü (dikey veya yatay), hizalamayı ve aralığı belirler. Tek tek öğeler boyutlarını ve kenar boşluklarını ince ayar yapabilir ya da gerektiğinde mutlak veya sabit konumlandırmayla akışın dışına çıkabilir. :::link Dolgu, kenarlık ve efektler gibi görsel özellikler için bkz. [Stiller ve görünüm](builder-styling). ::: <Tabs groupId="video"> <TabItem value="align" label="Hizalama ve konumlandırma"> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/aRS4Bzb6W4I?si=qH7B6t3kMab70gBi" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ``` </TabItem> <TabItem value="layout" label="Layout, boyut ve aralık"> ``` <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/WQ9fpxrndok?si=ROMdIPvJ32tSwUX6" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> </TabItem> </Tabs> ## Düzen \{#layout\} Düzen, ekrandaki öğeleri yerleştirmenin temel aracıdır. Her kapsayıcı, içindeki öğeleri belirli kurallara göre otomatik olarak dağıtır: yön, hizalama ve boşluk. Oluşturucu içinde kullanılabilen düzen öğeleri şunlardır: * **[Dikey Konteyner](builder-containers#containers)**: Çocuk öğeleri yukarıdan aşağıya sıralar * **[Yatay Konteyner](builder-containers#containers)**: Çocuk öğeleri soldan sağa sıralar * **[Ayırıcı](builder-containers#dividers)**: Öğeler arasında görsel bir ayraç * **[Carousel](builder-containers#carousel)**: Yatay kaydırılabilir slayt seti * **[Bottom Sheet](builder-containers#bottom-sheet)**: Kullanıcı bir düğmeye dokunduğunda ek içeriği ortaya çıkaran kayan bir bindirme panel Konteynerler, bir ekranın temel yapı taşlarıdır. Karmaşık düzenler oluşturmak için iç içe yerleştirebilirsiniz. Her konteynerin sağ panelinde, alt öğelerin nasıl dağıtılacağını kontrol eden bir **Layout** bölümü bulunur. Öğeleri yeni bir konteynerde gruplamak için **Wrap** [katman eylemini](paywall-layout-and-products#layer-actions) kullanın. Bir konteyneri kaldırıp alt öğelerini üst seviyeye taşımak için ise **Unwrap**'i kullanın. :::link Ekran ve katman hiyerarşisi hakkında ayrıntılı bilgi için bkz. [Ekranlar ve Katmanlar](paywall-layout-and-products). ::: ### Yön \{#direction\} * Free **Free**: Otomatik düzen yok. Alt öğeler bağımsız olarak konumlandırılır (alt öğelerin mutlak konumlandırma kullandığı durumlarda kullanışlıdır) * Vertical **Vertical**: Alt öğeler yukarıdan aşağıya, bir sütundaki satırlar gibi sıralanır * Horizontal **Horizontal**: Alt öğeler soldan sağa, bir satırdaki öğeler gibi dizilir ### Öğe sırası \{#element-order\} Alt öğeler, **Layers** panelinde göründükleri sırayla render edilir. Dikey bir container'da, listenin en üstündeki öğe ekranın en üstünde görünür. Yatay bir container'da ise en üstteki öğe solda yer alır. Öğeleri yeniden sıralamak için Layers panelinde sürükleyebilir ya da **Move Up** ve **Move Down** [katman eylemlerini](paywall-layout-and-products#layer-actions) kullanabilirsiniz. ### Hizalama \{#alignment\} Hizalama ızgarası, alt öğelerin kapsayıcının çapraz ekseninde nereye yerleşeceğini belirler. Dikey bir kapsayıcıda hizalama, alt öğelerin yatay konumunu (sol, orta veya sağ) kontrol eder. Yatay bir kapsayıcıda ise dikey konumlarını (üst, orta veya alt) belirler. ### Dağılım \{#distribution\} Dağılım, ana eksen boyunca çocuklar arasındaki alanın nasıl bölüneceğini belirler: * **Gap** Gap (varsayılan): Bitişik çocuklar arasında sabit piksel değeri * **Space Between**: Çocuklar kenarlara yayılır; aralarında eşit boşluklar oluşur * **Space Around**: Her çocuğun etrafında eşit boşluk bulunur, kenarlarda yarı boyutunda boşluklar yer alır * **Space Evenly**: Tüm çocukların önünde, arasında ve sonrasında eşit boşluk bulunur ### İçeriği kırp \{#clip-content\} Konteynerin sınırlarını aşan içeriği görsel olarak kırpar. Bir rozet gibi kartın kenarını kasıtlı olarak taşan öğelere izin vermek istiyorsanız bu seçeneği devre dışı bırakın. ## Konum \{#position\} Varsayılan olarak, her öğenin konumu kapsayıcısının düzeni tarafından otomatik olarak belirlenir. **Position** geçişi, öğeyi normal akışın dışına çıkararak konumunu elle belirlemenizi sağlar. ### Göreli (varsayılan) \{#relative-default\} Öğe, normal düzen akışında kalır. Konumu, üst kapsayıcının düzen kuralları tarafından otomatik olarak belirlenir — serbestçe sürükleyemezsiniz. Göreli bir öğenin çevresindeki boşluğu ayarlamak için **Margin** kullanın. Metin blokları, görseller, kartlar, düğmeler ve liste öğeleri gibi içeriklerin büyük çoğunluğu için göreli konumlandırmayı kullanın. ### Mutlak \{#absolute\} Element, normal akışın dışına çıkar ve diğer içeriklerin üzerine yerleşir. Artık komşu elementlerin düzenini etkilemez. **Absolute** seçtiğinizde ek kontroller görünür: * **Offset alanları** (T, L, R, B): Elemanın üst kapsayıcısının her kenarına olan uzaklığı piksel cinsinden belirler * **Anchor grid**: 3×3 ızgara üzerinde bir noktaya tıklayarak elemanın üst kapsayıcının hangi köşesine, kenarına veya merkezine bağlanacağını seçin * **Yatay anchor** Horizontal positioning (Left / Center / Right) ve **Dikey anchor** Vertical positioning (Top / Center / Bottom): Izgarayla aynı anchor noktasını kontrol eden açılır menüler * **Z-index**: Elemanın kardeş elemanlara göre [yığılma sırasını](#stacking-order) belirleyen sayısal alan. Daha yüksek değere sahip elemanlar üstte görünür Görsel üzerine yerleştirilen dekoratif katmanlar, rozetler, kapat düğmeleri ve ikonlar için mutlak konumlandırma kullanın. :::tip Mutlak bir öğeyi üst elemanının tam genişliğine yayımlak için yatay çapayı **Left** olarak ayarlayın, ardından **Right** ofsetine 0 ekleyin. Öğe her iki kenara da sabitlenir. ::: ### Sabit \{#fixed\} Öğe, üst kapsayıcısını tamamen yok sayar ve ekrana sabitlenir. Kullanıcı kaydırırken görünür kalır — sayfa içeriği onun altında hareket eder. Sabit konumlandırma, Mutlak ile aynı kontrolleri kullanır (offsetler, çapa ızgarası, Z-index). Tüm offsetler, üst öğeye değil ekranın güvenli alanına göre hesaplanır. Örneğin, alttan 0 offset, öğeyi home indicator'ın üzerinde tutar. Offsetleri fiziksel ekran kenarlarından ölçmek için [Güvenli alanı yoksay](#ignore-safe-area) seçeneğini etkinleştirin. Kaydırılan içeriğin üzerinde yüzmesi gereken öğeler için — kayan kapat veya geri yükleme düğmeleri, sabit üst bannerlar, yukarı kaydırma kontrolleri ve gezinme çubukları — sabit konumlandırma kullanın. Ayrılmış bir alt eylem alanı için bunun yerine bir [Footer](builder-containers#footer) kullanın. ### Güvenli alanı yoksay \{#ignore-safe-area\} Güvenli alan, ekranın çentik, durum çubuğu ve ana ekran göstergesinden uzak kalan bölümüdür. Varsayılan olarak, konumlandırılmış öğeler bu alanın içinde kalır. Öğenin uzaklıklarını fiziksel ekran kenarlarından ölçmek için konum türü seçicisinin altındaki **Ignore safe area** onay kutusunu işaretleyin. Bu sayede öğe çentiğin ve ana ekran göstergesinin arkasına kadar uzanabilir. Tam ekran kaplayan medya için şu yolu izleyin: görseli veya videoyu **Fixed** olarak konumlandırın, dört taraftaki offset değerlerini 0 yapın ve **Ignore safe area** seçeneğini işaretleyin. Medya, ekranın tamamını kenardan kenara kaplar. Bu onay kutusu yalnızca absolute ve fixed konumlandırma için çalışır. Göreli (relative) öğelerde devre dışı kalır; bir öğeyi **Relative** konumuna geri aldığınızda bu ayar otomatik olarak temizlenir. ## Boyutlandırma \{#sizing\} Her elementin **Width** ve **Height** kontrolleri vardır. Boyutlandırma modunu seçmek için açılır menüye tıklayın: * **Fill**: Öğe, üst öğesindeki tüm kullanılabilir alanı kaplayacak şekilde genişler. Gösterilen piksel değeri hesaplanan sonuçtur. * **Hug**: Öğe, içeriğine sığacak şekilde küçülür. Gösterilen piksel değeri hesaplanan sonuçtur. * **Fixed**: Öğe, üst öğesinden veya içerik boyutundan bağımsız olarak belirttiğiniz tam piksel değerini kullanır. Mutlak veya sabit konumlandırmalı öğeler için kullanılabilen tek moddur. ## Aralık \{#spacing\} Her kenar için aralık değerlerini bağımsız olarak ayarlayın. * **Margin**: Öğe ile komşuları arasındaki boşluk. Üst kapsayıcının sınırlarını aşmaz. * **Padding**: Öğenin sınırı ile içeriği arasındaki boşluk. Metin öğelerinde yalnızca margin bulunur. Ekranlarda yalnızca padding bulunur. Kapsayıcılarda ve alt içeriğe sahip diğer öğelerde her ikisi de kullanılabilir. ## Yığın sırası \{#stacking-order\} Göreceli öğeler hiçbir zaman birbiriyle çakışmaz — her container, alt öğelerini sırayla yerleştirir. Çakışma yalnızca bir öğe **Absolute** veya **Fixed** konumlandırmayla normal akışın dışına çıktığında gerçekleşir. Öğeler çakıştığında, **Layers** panelinde sonraki kardeş öğeler öncekilerinin üzerinde görüntülenir — sonraki kardeş göreceli, önceki ise mutlak konumlandırmalı olsa bile. **Absolute** ve **Fixed** öğeler, daha hassas kontrol için bir **Z-index** alanına sahiptir: daha yüksek değerler öncelik kazanır. Relative öğelerin Z-index değeri yoktur — katman sırası tek başına yığma düzenini belirler. Öğe sırasını değiştirmek için **Move up** ve **Move down** [katman eylemlerini](paywall-layout-and-products#layer-actions) kullanın. --- # File: builder-styling --- --- title: "Stiller ve görünüm" description: "Öğelerin görsel görünümünü yapılandırın — dolgu, kenarlık, efektler, tipografi, durumlar ve proje genelindeki stiller." --- **Design** sekmesi, sağ panelde her öğenin görsel görünümünü kontrol eder. Kullanılabilir özellikler öğe türüne göre değişse de çoğu öğe ortak stil seçeneklerini paylaşır. :::link Boyutlandırma, boşluk ve konumlandırma için bkz. [Düzen ve konumlandırma](manage-paywall-ui-elements). ::: ## Görünürlük \{#visibility\} **Visibility** (Görünürlük) düğmesi, öğenin ekranda görünüp görünmeyeceğini belirler. * Show **Show** (varsayılan): Öğe her zaman görünür. * Conditional **Conditional**: Öğe yalnızca belirli koşullar sağlandığında görünür. Daha fazla bilgi için bkz. [Koşullu görünürlük](onboarding-element-visibility). * Hide **Hide**: Öğe her zaman gizlidir. Bir öğeyi silmeden flow'dan geçici olarak kaldırmak için bunu kullanın. <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/3w3YSOmI3tQ?si=vPhoQGt44SI285Ru" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Doldur \{#fill\} **Fill** bölümü, öğenin arka planını kontrol eder. Dört farklı dolgu türü mevcuttur: düz renk, gradyan, resim ve video. Bu özelliği tüm ekranın ana görseli / videosu olarak ayarlamak için kullanın. * **Düz renk** Solid color. Renk seçiciyi kullanın, hex değeri girin veya [proje genelinde bir renk stili](#color-styles) atayın. Arka planı yarı saydam yapmak için **opaklık** değerini ayarlayın. * **Gradyan** Gradient. İki veya daha fazla renk duraklamasıyla gradyan dolgu ekleyin. Geçişi ayarlamak için duraklamaları sürükleyin, yönünü kontrol etmek için gradyan açısını değiştirin. * **Image** Image veya **Video** Video. Elementin arka planı olarak bir [resim / video](custom-media) ayarlayın. ## Kenarlık \{#border\} Kenarlıklar varsayılan olarak kapalıdır. Eklemek için sağ panelde **Border** yanındaki Plus simgesine tıklayın. Kenarlığı kaldırmak için **Border** başlığının yanındaki Close simgesine tıklayın. Kenarlık eklendiğinde şu ayarları yapılandırabilirsiniz: * **Color**: Renk seçiciyi kullanın, hex değeri girin veya [proje genelinde bir renk stili](#color-styles) atayın. Kenarlığı yarı saydam yapmak için **opacity** değerini ayarlayın. * **Width**: Piksel cinsinden kenarlık kalınlığı. ## Köşeler \{#corners\} **Corners** bölümü, köşe yuvarlaklığını (yuvarlak köşeler) kontrol eder. * **Radius slider**: Dört köşenin tamamı için aynı yarıçapı ayarlar * **Per-corner toggle** Per Corner: Her köşe için ayrı ayrı yarıçap belirlemek üzere etkinleştirin ## Efektler \{#effects\} Bir veya daha fazla görsel efekt eklemek için **Effects** yanındaki artı düğmesine Plus tıklayın: * **Drop shadow**: Elementin arkasında bir gölge * **Inner shadow**: Elementin sınırları içinde bir gölge * **Background blur**: Arka planı bulanıklaştırır * **Layer blur**: Elementi ve alt öğelerini bulanıklaştırır Aynı element üzerine birden fazla efekt ekleyebilirsiniz. Bir efekti geçici olarak devre dışı bırakmak için görünürlüğünü Show açıp kapatın. ## Animasyon \{#animation\} Animasyonlu bir efekt eklemek için **Animation** öğesinin yanındaki Plus düğmesine tıklayın. Şu an için yalnızca **Pulse** animasyonu mevcut — element dikkat çekmek amacıyla ritmik biçimde büyüyüp küçülür. Pulse animasyonunu aşağıdaki parametrelerle yapılandırabilirsiniz: | Parametre | Açıklama | |-----------|-------------| | Ölçek miktarı (%) | Öğenin orijinal boyutuna göre ne kadar büyüdüğü | | Süre (ms) | Tek bir animasyon döngüsünün uzunluğu | | Döngüler arası gecikme (ms) | Tekrarlar arasındaki duraklama | | Gölge rengi | Nabız atan gölge efektinin rengi | | Gölge boyutu (px) | Nabız atan gölgenin boyutu | ### Animasyonu önizleme \{#preview-the-animation\} Builder varsayılan olarak statik ekranlar gösterir — animasyonlar siz etkinleştirene kadar hareketsiz kalır. İki yöntem: - Cihaz önizlemesinin üstündeki **Toggle animations** Toggle animations düğmesine tıklayın. Ekranın animasyonlarını açar veya kapatır — açıldıktan sonra siz tekrar tıklayana kadar sürekli çalışır. Düğme yalnızca aktif ekranda en az bir animasyon olduğunda görünür. - Ekranın [bağlam menüsünü](paywall-layout-and-products#screen-actions) açın (ekran katmanının yanındaki üç nokta simgesi) ve **Play Animation** seçeneğini belirleyin. ## Görünüm \{#appearance\} * **Opacity**: %0 (şeffaf) ile %100 (opak) arasında değer alır * **Rotation**: Öğeyi döndürmek için derece cinsinden bir değer girin ## Tipografi özellikleri (metin öğeleri) \{#typography-properties-text-elements\} Metin öğelerinde aşağıdaki denetimleri içeren bir **Typography** bölümü görüntülenir: ### Yazı Tipi \{#font\} :::link Ayrıca bakınız: [Özel yazı tipleri](using-custom-fonts-in-flow-builder) ::: Yazı tipi seçici açmak için yazı tipi açılır menüsüne Font select tıklayın. İki sekme bulunur: * **Styles**: Projenizin kayıtlı [metin stillerini](#text-styles) listeler. Tüm tipografi ayarlarını bir anda uygulamak için bir stil seçin. * **Fonts**: Mevcut tüm yazı tipi ailelerini listeler. İhtiyacınız olanı bulmak için arama yapın veya kaydırın. Yerleşik yazı tipleri **cihazlar arasında farklı görünebilir** — tutarlı bir görünüm için [özel yazı tipi](using-custom-fonts-in-flow-builder) yükleyin. ### Boyut ve kalınlık \{#size-and-weight\} :::warning [Özel fontlar](using-custom-fonts-in-flow-builder) için **Weight**, **Bold** ve **Italic** kontrolleri yalnızca editörün yerleşik önizlemesini etkiler. Farklı kalınlık ve stilleri göstermek için fontu her varyasyon için ayrı bir dosya olarak yükleyin. ::: * **Weight**: Açılır listeden bir font kalınlığı seçin * **Size**: Açılır listeden bir boyut seçin ya da özel bir değer girin ### Renk \{#color\} Renk seçiciyi açmak için renk kutucuğuna tıklayın. Hex değeri girin, paleti kullanın veya [yeniden kullanılabilir stillerden](#reusable-styles) birini seçin. Metni yarı saydam yapmak için opaklık kaydırıcısını ayarlayın. ### Hizalama \{#alignment\} İki grup hizalama kontrolü: * **Yatay**: Sol Align left, Orta Align center veya Sağ Align right * **Dikey**: Üst Align top, Orta Align middle veya Alt Align bottom ### Dekorasyon \{#decoration\} * **None** None: Dekorasyon yok (varsayılan) * **Underline** Underline: Metne alt çizgi ekler * **Strikethrough** Strikethrough: Metne üstü çizgi ekler ### Kırpma \{#truncation\} Metnin **Maks. Satır** ayarını aşması durumunda kırpma özelliğini etkinleştirerek metni belirli bir noktada kesin. Bu özellik özellikle birden fazla dili desteklerken işe yarar: çevrilen bir metin orijinalden uzunsa, kırpma düzenin bozulmasını önler. :::note Bir metin öğesi seçtiğinizde, canvas üzerinde öğenin hemen üstünde bir **satır içi araç çubuğu** da görünür. Bu araç çubuğu, sağ panelde aşağı kaydırmadan yazı tipi, kalınlık, boyut ve hizalama ayarlarına hızlıca erişmenizi sağlar. ::: ## Duruma özgü ayarlar (etkileşimli öğeler) \{#state-specific-settings-interactive-elements\} Etkileşimli öğeler birden fazla görsel durumu destekler. Böyle bir öğe seçtiğinizde, sağ panelde **States** bölümü belirir. Her durum için farklı görsel özellikler ayarlamak üzere durumlar arasında geçiş yapın. Her durum, dolgu, kenarlık, tipografi rengi, opaklık ve daha fazlası gibi görsel özellikleri ayrı ayrı geçersiz kılabilir. ### Seçilebilir durumlar \{#selectable-states\} :::link Ana makale: [Seçilebilir öğeler](flow-selectable-elements) ::: Seçilebilir bir gruba ait öğeler (quiz seçenekleri, ürünler, sekmeler, deneme süresi toggle'ları) varsayılan olarak iki durum sunar: * **Default**: Öğenin normal görünümü * **Selected**: Kullanıcı bu seçeneği seçtiğindeki görünüm. Aktif seçimi vurgulamak için fill, kenarlık rengi ve metin rengi gibi özellikleri özelleştirin Seçilebilir bir öğeyi etkileşimde bulunulamaz durumdayken stillemek için üçüncü bir durumu elle ekleyin. **States settings** Settings bölümünü açın ve **Disabled state** ekleyin. **Disabled** durumu koşula bağlıdır. Bunu seçin ve çalışma zamanında öğenin ne zaman devre dışı kalacağını tanımlamak için **Set conditions** set conditions seçeneğine tıklayın; örneğin zorunlu bir alan boş olduğunda. ### Giriş alanı durumları \{#input-states\} Giriş alanları ek durumlar sunar: * **Default**: Normal, odaklanmamış görünüm * **Active**: Alan odaklanmış ve giriş yapmaya hazır * **Invalid**: Girilen değer doğrulamayı geçemiyor * **Disabled**: Alan etkileşime kapalı ### Durum taşıyan diğer öğeler \{#other-state-bearing-elements\} Birkaç öğe, standart **Varsayılan / Seçili / Devre Dışı** düzeninin dışında duruma özgü stil sunar: - **[İlerleme göstergesi adımları](builder-loaders-and-progress-bars#step-states)** — her adım için üç durum: **Completed**, **Current** ve **Upcoming**. - **[Carousel dots](builder-containers#dots)** — iki renk varyantı: etkin olmayan noktalar için **Color** ve geçerli slaydın noktası için **Active Color**. ## Yeniden kullanılabilir stiller \{#reusable-styles\} Sol kenar çubuğundaki **Styles** Styles paneli, flow'unuz genelinde geçerli olacak yeniden kullanılabilir stiller tanımlamanıza olanak tanır. İki tür stil mevcuttur: metin stilleri ve renk stilleri. Karanlık mod desteğini etkinleştirmek için renk stillerini kullanmanız gerekir. ### Metin stilleri \{#text-styles\} :::link Ana makale: [Metin içeriği](onboarding-text) ::: Metin stilleri, tipografi ayarlarının tamamını barındırır — font ailesi, kalınlık, boyut, satır yüksekliği, hizalama ve dekorasyon. Her flow şablonu varsayılan ön ayarlarla gelir; dilediğiniz özel stiller de oluşturabilirsiniz. Metin stili oluşturmak için: 1. **Styles** Styles panelini açın ve **Text** sekmesini seçin. 2. **Plus Create style** seçeneğine tıklayın. 3. Bir ad girin ve tipografi ayarlarını yapılandırın. 4. **Create** seçeneğine tıklayın. Bir metin stili uygulamak için bir metin öğesi seçin ve **Typography** bölümündeki yazı tipi açılır menüsünden stili seçin. ### Renk stilleri \{#color-styles\} Renk stilleri, flow'unuzun her yerinde başvurabileceğiniz adlandırılmış renklerdir. Her renk stilinin bir adı (örneğin "Primary text" veya "Brand"), bir hex değeri ve kaç öğenin bu stile başvurduğunu gösteren bir kullanım sayısı vardır. Renk stili oluşturmak için: 1. **Styles** Styles panelini açın ve **Colors** sekmesini seçin. 2. **Plus Create style** seçeneğine tıklayın. 3. Bir ad girin ve renk seçin. Bir renk stilini güncellediğinizde, ona başvuran tüm öğeler otomatik olarak güncellenir. ### Karanlık mod \{#dark-mode\} :::link Ana makale: [Karanlık mod](paywall-dark-mode) ::: Gerekirse, her renk stiline iki varyant ekleyebilirsiniz — biri açık mod Light mode için, diğeri karanlık mod Dark mode için. SDK, cihazın mevcut renk şemasına göre doğru varyantı otomatik olarak uygular. Oluşturucuda koyu modu önizlemek için [alt araç çubuğundaki](builder-ui#view-controls-bottom-toolbar) **tema değiştirici** düğmesini Dark mode kullanın. --- # File: paywall-product-block --- --- title: "Satın alma işlemlerini ayarlama" description: "Flow Builder'da ürünleri ekranlara atayın, ürün öğeleri ekleyin ve bir satın alma düğmesi bağlayın." --- Bir ekranda satın alma işlemlerini ayarlamak için bir satın alma düğmesi ekleyin ve **Purchase** eylemini yapılandırın. Eylem, belirli bir ürünü veya kullanıcının ekrandaki Products öğesinden seçtiği ürünü hedefleyebilir. <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/LLIZCd94PlE?si=t_8BitA1FBpbd8ue" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Ürün ekle \{#add-products\} Ürün elementi, canvas üzerinde bir ürünü gösteren görsel bir karttır. Ürün elementi eklemek için: 1. Canvas üzerinde hedef ekranda **+** simgesine tıkla. 2. **Products** seçeneğini seç. 3. Bir düzen şablonu seç: dikey liste, yatay liste, özellik karuseli, özellik kartları, banner liste veya alt sayfa. 4. Her ürün kartını seç ve **Design** panelindeki açılır menüden bir ürün ata. :::important Ürün öğesi, bağlı bir ürün olmadan [önizleme ve yayınlamayı engeller](builder-save-publish#troubleshooting). Bir ürün atayın veya öğeyi silin. ::: Kartta üstü çizili bir çapa fiyatı göstermek için içine bir [Eski Fiyat öğesi](onboarding-text#add-an-old-price) ekleyin. :::note Bir **Satın Al** eylemini doğrudan bir ürün kartının **On tap** etkileşimine de ekleyebilirsiniz. Karta dokunulduğunda satın alma işlemi tetiklenir; ayrı bir satın alma düğmesine gerek kalmaz. ::: :::important Bir ürün grubunu silip yerine yeni bir tane eklerseniz, tüm eylem ve değişkenlerin yeni grubu hedef aldığından emin olun. Silinen grubu işaret eden referanslar [önizleme ve yayınlamayı engeller](builder-save-publish#troubleshooting). ::: ## Satın alma düğmesi ekleme \{#add-a-purchase-button\} Satın alma düğmesi, kullanıcı üzerine dokunduğunda bir **Purchase** eylemi tetikler. Satın alma düğmesi eklemek için: 1. Tuval üzerinde ekrana ait **+** simgesine tıklayın. 2. **Button** seçeneğini seçip bir buton ön ayarı belirleyin. 3. Buton seçiliyken sağ paneldeki **Interactions** sekmesini açın. 4. **Add trigger** > **On tap** seçeneğine tıklayın, ardından **Add action** seçeneğine tıklayın. 5. **Action** alanını **Purchase** olarak ayarlayın, ardından **Product** alanını aşağıdakilerden biri olarak ayarlayın: - `products.selectedProduct`: Kullanıcının ekrandaki Products öğesinden seçtiği ürünü satın alır. - Belirli bir ürün: Ekrandaki herhangi bir seçimden bağımsız olarak her zaman o ürünü satın alır. ### Düğmede fiyatı gösterme \{#show-the-price-on-the-button\} Seçili ürünün fiyatını düğme etiketine eklemek için bir değişken kullanın: 1. Düğme seçiliyken sağ panelde **Design** sekmesini açın. 2. **Content** alanında imleci fiyatın görünmesini istediğiniz yere getirin. 3. Değişken simgesine tıklayın, `products.selectedProduct` seçeneğini, ardından `prod_price` özniteliğini seçin. Tam değişken `products.selectedProduct.prod_price` olarak çözümlenir. 4. Değişkenin etrafına sabit metin ekleyin — örneğin `Subscribe for {prod_price}`. Kullanıcı farklı ürünler seçtikçe etiket güncellenir. ## Satın almaları geri yükle \{#restore-purchases\} Kullanıcıların önceki satın almalarını geri yükleyebilmesi için ekrana bir geri yükleme düğmesi veya bağlantısı ekleyin. Satın almaları geri yükle öğesi eklemek için: 1. Tuval üzerinde ekranın **+** simgesine tıklayın. 2. **Button** seçeneğini seçin, ardından metin bağlantısı için **Links**'i ya da biçimlendirilmiş bir düğme için başka bir düğme türünü seçin. 3. Öğe seçili durumdayken, sağ panelde **Interactions** sekmesini açın ve **Add trigger** butonuna tıklayın. 4. **On tap** seçeneğini seçin ve **Add action** butonuna tıklayın. 5. **Action** açılır menüsünden **Restore purchases** seçeneğini seçin. ## Seçilen ürüne göre ek öğeleri görüntüleme \{#display-additional-elements-based-on-the-selected-product\} Bir ekranda ürünler varsa, kullanıcının hangi ürünü seçtiğine bağlı olarak diğer öğeleri gösterip gizleyebilirsiniz. Koşullu görünürlüğü ayarlamak için: 1. **Products** öğesinde bir ürün kartı seçin. 2. Sağ panelde **Interactions** sekmesini açın ve **Add trigger** seçeneğine tıklayın. 3. **On tap** seçeneğini belirleyin ve **Add action** düğmesine tıklayın. 4. **Action** açılır menüsünden **Show** veya **Hide** seçeneğini belirleyin. 5. İlgili ürün seçildiğinde gösterilecek veya gizlenecek öğeyi seçin. ## Flow içindeki ürünleri inceleme \{#review-products-in-flow\} Sol kenar çubuğundaki **Products** paneli, mevcut ürünleri flow'daki her ekranla eşleştirir. Her ekranın iki bölümü vardır: - **Default** — ekran yüklendiğinde önceden seçili olan tek ürün. - **Other** — aynı ekranda kullanılabilen ek ürünler. --- # File: flow-selectable-elements --- --- title: "Seçilebilir öğeler ve gruplar" description: "Öğeleri seçilebilir hale getirin, gruplar halinde düzenleyin ve durumlarını flow genelinde koşullarda kullanın." --- Seçilebilir öğeler, kullanıcıların dokunarak seçip kaldırabileceği flow öğeleridir. Bu öğelerin durumu, flow genelinde gezinme, görünürlük ve diğer mantıksal işlemleri yönlendirebilir. Şunları yapabilirsiniz: - [Varsayılan seçilebilir öğeleri kullanın](#default-selectable-elements) — quiz seçenekleri, ürünler, sekmeler ve deneme süresi geçişleri kutudan çıkar çıkmaz seçilebilir durumda gelir - [Herhangi bir öğeyi seçilebilir yapın](#make-an-element-selectable) — istediğiniz öğeyi seçilebilir hale getirin ve bir gruba atayın - [Gruplar oluşturun ve yönetin](#create-a-group) — seçilebilir öğeleri tek seçimli, çok seçimli veya geçiş gruplarına göre düzenleyin - [Koşullarda seçili durumu kullanın](#use-selectable-state-in-conditions) — flow içindeki herhangi bir ekranda grup değerlerine koşullarda başvurun ## Varsayılan seçilebilir öğeler \{#default-selectable-elements\} Bazı öğe türleri varsayılan olarak seçilebilir durumdadır — bunlar otomatik oluşturulan gruplara zaten aittir ve ek kurulum gerektirmez: - **Quiz seçenekleri**: Her quiz cevabı, quiz grubu içinde seçilebilir bir öğedir. Bkz. [Quiz'ler](onboarding-quizzes). - **Ürünler**: Bir ürün grubundaki ürün kartları. Bkz. [Ürün bloğu](paywall-product-block). - **Sekmeler**: Sekme grubu içindeki sekme öğeleri. Bkz. [Sekmeler](builder-tabs). - **Deneme süresi geçişleri**: Bir gruba ait olan ve seçili durum alan bir container. Bkz. [Geçişler](builder-toggles). ## Bir öğeyi seçilebilir yapma \{#make-an-element-selectable\} <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/btpZPOm9VRY?si=1P959iwNfIJ1ZP7N" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Bazı durumlarda ek öğeleri seçilebilir hale getirmek isteyebilirsiniz. Örneğin, bir quiz grubunun içinde öğe olarak işlev gören bir **Don't ask me again** onay kutusu ekleyebilirsiniz. Bir öğeyi seçilebilir hale getirmek için: 1. Ekranda veya **Layers** panelinde öğeyi seçin. 2. Sağ tarafta **Interactions** paneline geçin. 3. **Turn into selectable element** seçeneğini belirleyin. 4. **Group** açılır menüsünde mevcut bir grubu seçin ya da [yeni bir grup oluşturun](#create-a-group). 5. **Element ID**'yi belirleyin — bu, gruptaki öğe için benzersiz bir tanımlayıcıdır. 6. Bu öğenin varsayılan olarak seçili olmasını istiyorsanız **Set as default in group** onay kutusunu işaretleyin. ## Grup oluşturma \{#create-a-group\} Gruplar, bir ekrandaki seçilebilir öğeleri düzenler ve seçimin nasıl çalışacağını tanımlar — kullanıcıların tek seçenek, çoklu seçenek ya da geçiş (toggle) yapıp yapamayacağını belirler. Grup oluşturmak için: 1. Bir öğe seçin ve [seçilebilir hale getirin](#make-an-element-selectable). 2. **Group** açılır menüsünde **Create group** seçeneğini tıklayın. 3. Bir **Group name** girin. 4. [Grup türünü](#group-types) seçin. Grup artık aynı ekrandaki diğer seçilebilir öğeler için **Group** açılır menüsünde görünür. ## Grup türleri \{#group-types\} :::important Çoğu [quiz ön ayarı](onboarding-quizzes) varsayılan olarak **çoklu seçim** şeklindedir. Yalnızca tek yanıta izin vermek için [grup türünü](#manage-groups) değiştirin. ::: - **Tekli seçim**: Grupta aynı anda yalnızca bir öğe seçilebilir. Yeni bir öğe seçildiğinde önceki seçim kaldırılır. - **Çoklu seçim**: Aynı anda birden fazla öğe seçilebilir. - **Geçiş düğmesi**: Her öğe, diğer öğelerden bağımsız olarak her dokunuşta seçili ve seçilmemiş durumu arasında geçiş yapar. ## Grupları yönetme \{#manage-groups\} Grupları görüntülemek ve düzenlemek için **Screen settings** panelini açın ve **Selectable groups** bölümünü bulun. Bu bölümde mevcut ekrandaki tüm gruplar listelenir. Bir grup ID'sine tıklayarak şunları yapabilirsiniz: - Grup ID'sini değiştirme - [Grup türünü](#group-types) değiştirme - Grup öğelerinin koşullarda nasıl referans alındığını görme ## Koşullarda seçilebilir durumu kullanma \{#use-selectable-state-in-conditions\} Bir grubun seçili durumunu, flow'daki herhangi bir ekrandaki koşullarda referans olarak kullanabilirsiniz — grubun tanımlandığı ekranla sınırlı değilsiniz. Örneğin: `IF quiz.photo is selected, THEN navigate to the Photo screen`. :::important Bir gruptaki tüm elemanlar aynı ekranda olmalıdır. Farklı ekranlardaki elemanları tek bir gruba ekleyemezsiniz. Ancak grup değerlerini flow'daki herhangi bir ekrandaki koşullarda referans olarak kullanabilirsiniz. ::: Seçilebilir durumu şunlarla kullanın: - **[Koşullu eylemler](onboarding-actions#conditional-actions)**: Seçilen öğelere göre kullanıcıları farklı ekranlara yönlendirin veya farklı eylemler tetikleyin. - **[Dinamik navigasyon](onboarding-navigation-branching)**: Quiz yanıtlarına, toggle durumlarına veya diğer seçimlere göre flow'u dallandırın. - **[Koşullu görünürlük](onboarding-element-visibility)**: Kullanıcıların önceki ekranlarda seçtiklerine göre öğeleri gösterin veya gizleyin. --- # File: builder-element-states --- --- title: "Element durumları" description: "Öğeleri duruma göre biçimlendirin ve çalışma zamanında bir koşul kullanarak bir öğeyi devre dışı bırakın." --- Etkileşimli flow elemanları, kullanıcı etkileşimlerine göre görünümlerini değiştirir: seçilen bir sınav seçeneği **Seçili**, odaklanan bir giriş alanı **Aktif** görünüm alır. Bazı durumlar koşula bağlıdır — örneğin bir düğmeyi **devre dışı bırakabilirsiniz**. Kullanıcılara uygulama kodu yazmadan görsel geri bildirim vermek için her durumu ayrı ayrı stilleyin. <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/gdsNfHpKAqQ?si=VY5mqZgH1j0RB6fE" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Eleman türüne göre kullanılabilir durumlar \{#available-states-by-element-kind\} | Eleman türü | Yerleşik durumlar | Eklenebilir durumlar | |---|---|---| | [Seçilebilir elemanlar](#selectable-element-states) | **Default**, **Selected** | **Disabled** | | [Girdiler](#input-states) | **Default**, **Active**, **Invalid** | **Disabled** | | [Dokunma etkileşimi olan herhangi bir eleman](#condition-driven-disabled-state) — düğmeler, görseller, ikonlar, kapsayıcılar vb. | **Default** | **Disabled** | | [İlerleme göstergesi adımları](#step-states-for-progress-indicators) | **Completed**, **Current**, **Upcoming** | — | **Eklenebilir** durumlar varsayılan olarak görünmez — eklemek için **States settings** Settings bölümünü açın. Bu durumlar [**koşula bağlı**](#condition-driven-disabled-state): ne zaman etkinleşeceklerini siz tanımlarsınız. ## Bir durumu nasıl stillendirirsiniz \{#how-to-style-a-state\} 1. Bir öğe seçin. Sağ paneldeki **States** bölümü, öğenin desteklediği durumları listeler. 2. **States** bölümünde hedef durumu etkinleştirin. Gerekirse [koşula bağlı Disabled durumunu](#condition-driven-disabled-state) ekleyin. 3. Herhangi bir özelliği değiştirin — dolgu, kenarlık, tipografi vb. Değişiklik yalnızca o duruma uygulanır. Nested öğeler, ana öğeyle birlikte durumlu hale gelir. Bir alt öğede yapılan her değişiklik, ana öğenin aktif durumuna göre uygulanır. 4. Builder, çalışma zamanında eşleşen stili uygular. ## Seçilebilir öğe durumları \{#selectable-element-states\} Seçilebilir öğeler — sınav seçenekleri, ürünler, sekmeler, deneme süresi geçiş düğmeleri ve herhangi bir [özel seçilebilir öğe](flow-selectable-elements#make-an-element-selectable) — kutudan çıkar çıkmaz iki duruma sahiptir: - **Varsayılan**: Öğenin dinlenme görünümü. - **Seçili**: Kullanıcı öğeye dokunduğunda uygulanır. Kullanıcı öğenin seçimini kaldırdığında Builder, Varsayılan duruma geri döner. Tek seçimli bir grupta, bir öğeyi seçmek diğerlerinin seçimini kaldırır. Çok seçimli gruplar aynı anda birden fazla öğenin Seçili olmasına izin verir. Toggle'lar birbirinden bağımsızdır — birini seçmek diğerlerini etkilemez. Bkz. [grup türleri](flow-selectable-elements#group-types). :::tip Birkaç öğe için aynı durumu stillemek mi istiyorsunuz (örneğin, test seçenekleri)? Önce bir öğeyi stilleyin, ardından kopyalayın. Durum stillendirmesi kardeş öğeler arasında aktarılmaz — şu anlık geçici çözüm bu. ::: ## Giriş durumları \{#input-states\} - **Varsayılan**: Giriş alanının normal görünümü. - **Aktif**: Giriş alanı odaklanmışken uygulanır. - **Geçersiz**: Giriş alanının içeriği doğrulamayı geçemediğinde uygulanır. Örneğin, bir e-posta alanında `@` karakteri bulunmadığında. Bkz. [Giriş doğrulama](builder-inputs-and-forms#input-validation). - **Devre Dışı**: Giriş alanı etkileşime kapalıdır. Bu durumu manuel olarak ekleyin; bkz. [Koşula dayalı Devre Dışı durumu](#condition-driven-disabled-state). Her durumu, seçilebilir bir öğede olduğu gibi biçimlendirin: hedef durumu etkinleştirin, ardından özellikleri değiştirin. ## Koşula Bağlı Devre Dışı Durumu \{#condition-driven-disabled-state\} Devre Dışı durumu, kullanıcının bir öğeyle etkileşim kurmasını engeller. Default, Selected, Active veya Invalid durumlarının aksine, Devre Dışı durumu kendi kendine etkinleşmez; kullanıcı tarafından tanımlanan bir tetikleyici koşul gerektirir. Devre Dışı durumu şu öğelerde kullanılabilir: - **Girişler**: Herhangi bir [giriş alanı](builder-inputs-and-forms) — metin, e-posta, şifre, sayı, telefon, tarih ve/veya saat. - **Seçilebilir öğeler**: Quiz seçenekleri, ürünler, sekmeler, deneme süresi geçişleri ve herhangi bir [özel seçilebilir öğe](flow-selectable-elements#make-an-element-selectable). - **Dokunma etkileşimi olan herhangi bir öğe**: Örneğin, bir gezinme eylemi tetikleyen bir düğme, resim veya simge. ### Devre dışı durumu ekleme \{#add-the-disabled-state\} Devre dışı durumu eklemek ve yapılandırmak için: 1. Hedef öğeyi seçin. 2. **States** bölümünde **Settings** Settings seçeneğine tıklayın. 3. **Add Disabled state** seçeneğini belirleyin. Disabled state, **States** bölümünde görünür. 4. Yeni Disabled state'in yanındaki **Edit conditional state** Edit conditional state seçeneğine tıklayın. 5. Bir koşul ekleyin. Girdi doğrulamayı geçmediği sürece **submit** düğmesini devre dışı bırakmak istiyorsanız, girdinin `isValid` değişkenini `false` ile karşılaştırın. 6. Kısıtlamayı görsel olarak iletmek için Disabled state'i stilize edin (örneğin, opaklığı düşürün). { } Adapty SDK, koşulu çalışma zamanında değerlendirir ve gerektiğinde Disabled durumunu uygular — herhangi bir uygulama kodu gerekmez. ## İlerleme göstergeleri için adım durumları \{#step-states-for-progress-indicators\} :::link Ana makale: [İlerleme göstergeleri](builder-loaders-and-progress-bars#step-states) ::: İlerleme göstergeleri, kullanıcıların onboarding flow'unda ne kadar ilerlediklerini gösterir. Her adımın üç durumu vardır: - **Tamamlandı**: Kullanıcının geçtiği adımlar. - **Mevcut**: Kullanıcının bulunduğu adım. - **Yaklaşan**: Kullanıcının henüz ulaşmadığı adımlar. --- # File: builder-containers --- --- title: "Düzen öğeleri: kapsayıcılar, döngüler, alt sayfalar" description: "Öğeleri Flow Builder'da kapsayıcılar, döngüler ve alt sayfalara göre gruplandırın." --- Düzen öğeleri, diğer öğeleri bir araya getirir ve ekranda nasıl yerleşeceğini kontrol eder. Flow Builder beş tür düzen öğesi içerir: - **Container'lar**: alt öğeleri bir eksen boyunca — dikey veya yatay — düzenler - **Carousel**: bir seferde tek slayt gösteren kaydırılabilir bir container - **Bottom Sheet**: ekranın altından yukarı kayan ve mevcut içeriğin üzerinde görüntülenen bir panel - **Footer**: kaydırma alanının dışında, ekranın altına sabitlenmiş bir panel - **Divider'lar**: satırları veya sütunları ayıran ince çizgiler :::link **Sekmeler** de bu kategoriye girer, ancak ayrı bir makalede ele alınmaktadır. Ayrıntılar için [Sekmeler](builder-tabs) bölümüne bakın. ::: ## Konteynerler \{#containers\} :::link Ana makale: [Element konumlandırma](manage-paywall-ui-elements) ::: Konteynerler, öğeleri dikey veya yatay olarak gruplar. **Vertical Container** öğeleri satırlar halinde; **Horizontal Container** ise sütunlar halinde düzenler. :::tip Daha karmaşık düzenler oluşturmak için konteynerleri iç içe yerleştirin. ::: ### Konteyner yönünü değiştirme \{#change-container-direction\} Bir konteynerin yönü sabit değildir. Sağ panelin **Layout** bölümünden istediğiniz zaman **Vertical**, **Horizontal** veya **Free** arasında geçiş yapabilirsiniz — konteyneri silip yeniden oluşturmanıza gerek yok. Aralık, hizalama ve dağılım ayarlarını da aynı **Layout** bölümünden yapabilirsiniz. Alt öğeler, **Layers** panelinde göründükleri sıraya göre render edilir — yeniden sıralamak için sürükleyip bırakın. ### Sarma ve sarımı kaldırma \{#wrap-and-unwrap\} Mevcut bir öğeyi container'a dönüştürmek için öğeyi seçin ve **Wrap** [katman eylemini](paywall-layout-and-products#layer-actions) kullanın. **Layers** panelinden yeni container'a ek öğeler sürükleyin. Bir container'ı kaldırıp içindeki öğeleri bir üst seviyeye taşımak için **Unwrap** kullanın. ## Carousel **Carousel**, bir seferde tek bir slayt gösteren, kaydırılabilir bir kapsayıcıdır. Kullanıcı sonraki slayta geçmek için yatay olarak kaydırabilir ya da carousel belirli bir zamanlayıcıyla otomatik olarak ilerleyebilir. Carousel, bir dizi **Slide** katmanı içerir. Bir slayt etkin olduğunda, o katmandaki öğeler ekranda görünür. Sekmelerden farklı olarak, carousel'in aktif slaytı bir [seçilebilir grup](flow-selectable-elements) olarak sunulmaz — slaytlar koşullarda veya dinamik metinlerde referans alınamaz. Carousel'i kullanıcı odaklı dallanma için değil, görsel döngü için kullanın. ### Aktif slaytı değiştirme \{#change-active-slide\} Karuseli seçtiğinizde, builder'da bir **Slide** açılır menüsü ve **+ Add Slide** düğmesi içeren açılır kontrol çubuğu görünür. - Yeni boş bir slayt eklemek için **+ Add Slide** düğmesine tıklayın. - Tuvalde hangi slaytın aktif olacağını değiştirmek için **Slide** açılır menüsünü kullanın ya da **Layers** panelindeki ilgili Slide katmanına tıklayın. Slaytları yeniden sıralamak için Layers panelindeki Carousel içinde sürükleyip bırakın. {/* TODO: on-device GIF */} ### Özellikler #### Otomatik kaydırma \{#auto-scroll\} Otomatik kaydırma, slaytları otomatik olarak döngüye sokar — kullanıcının tüm içeriği görmek için kaydırması gerekmez. İki zamanlama kontrolü davranışı belirler: - **Delay** — her slaytın ekranda kalma süresi (ms). - **Duration** — slaytlar arasındaki geçişin süresi (ms). #### Carousel boyutlandırma \{#carousel-sizing\} Özel kontroller, carousel'in boyutunu ve bitişik slaytlar arasındaki boşluğu belirler. Farklı içerik uzunluklarına sahip slaytlar arasında geçiş yaparken düzenin kaymaması için **Height** değerini **Fixed** olarak ayarlayın. #### Slayt boyutlandırma \{#slide-sizing\} Slayt başına **Width** ve **Height**. Varsayılan olarak Fill şeklindedir; bu sayede her slayt carousel'in boyutlarını takip eder. Bitişik slaytların kısmen görünür olduğu bir peek efekti oluşturmak için sabit bir genişlik ayarlayın. #### Noktalar \{#dots\} Karuselın alt kısmındaki sayfa göstergesi. Kullanıcıya kaç slayt olduğunu ve hangisinin aktif olduğunu gösterir. Slayt göstergesini gizlemek için **Show dots** geçiş düğmesini kapatın. Noktalar görünürken aşağıdaki özellikler görünümlerini belirler: - **Color** — aktif olmayan noktanın dolgu rengi. - **Active Color** — o an görüntülenen slaydın nokta dolgu rengi. - **Size** — her noktanın piksel cinsinden çapı. - **Gap** — bitişik noktalar arasındaki boşluk. - **Padding** — nokta satırı ile üzerindeki döngü içeriği arasındaki boşluk. ## Bottom Sheet :::link Kılavuz: [Tüm planları bir bottom sheet içinde göster](show-plans-bottom-sheet) ::: **Bottom Sheet**, ekranın alt kısmından yukarı doğru kayan ve mevcut içeriğin üzerinde görünen bir düzen panelidir. Sheet, arkasındaki her şeyi her zaman bulanıklaştırır; bu bulanıklık kapatılamaz. Ekran yüklendiğinde değil, bir dokunuşla tetiklenecek şekilde kullanın — örneğin bir **Show all plans** bağlantısının arkasına yerleştirin. ### Yapı \{#structure\} Bir Bottom Sheet iki üst düzey katmanla gelir: - **Heading** — sayfanın üstündeki bir kapsayıcıdır; önceden doldurulmuş bir **Title** metin katmanı ve bir **Close button** Close içerir. Gerektiğinde düzenleyebilir veya kaldırabilirsiniz. - **Content** — ana kapsayıcıdır. İçine ürünler, düğmeler, bağlantılar veya başka öğeler ekleyebilirsiniz. {/* TODO: on-device GIF */} ### Başlangıç görünürlüğü \{#initial-visibility\} Varsayılan olarak, bir alt sayfa ekran render edildiği anda görünür. Bunun yerine isteğe bağlı açmak için: 1. **Önce sayfanın içeriğini oluşturun** — gizli katmanlar düzenlenemez, bu nedenle doldurma işlemi bitene kadar sayfa görünür kalmalıdır. 2. **Layers** panelinde alt sayfayı seçin. 3. **Visibility** ayarını **Hide** Hide olarak ayarlayın. Sayfa, katman ağacında kalır ancak ekranda render edilmez. ### Alt sayfayı tetikleme \{#triggering-the-bottom-sheet\} Gizli bir alt sayfayı açmak için başka bir öğeye **Show** eylemi ekleyin: 1. Tetikleyici öğeyi seçin (örneğin, bir düğme veya metin bağlantısı). 2. Sağ panelde **Interactions** sekmesini açın. 3. **Add trigger** > **On tap** seçeneğine tıklayın, ardından **Add action** deyin. 4. **Action** alanını **Show** olarak ayarlayın ve açılır menüden alt sayfayı seçin. ## Alt Bilgi \{#footer\} **Footer**, ekranın alt kısmını kaplayan sabit bir kapsayıcıdır. İstediğiniz yükseklikte olabilir; tek bir düğmeden birden fazla metin satırına kadar her türlü içeriği barındırabilir. Ekranın geri kalanı kaydırılırken yerinde kalması gereken içerikler için footer'ı kullanın; CTA düğmeleri, yasal metinler ve bağlantılar bunlara örnek verilebilir. Sıradan öğelerden farklı olarak footer, cihazın alt güvenli alanına kadar uzanır: arka planı ekranın en alt kenarına dek devam eder. Ekran başına yalnızca bir alt bilgi (footer) kullanılabilir. Mevcut bir alt bilgiyi kopyalayamaz veya yeni bir tane ekleyemezsiniz. ### Alt bilgi mi, yoksa sabit bir öğe mi? \{#footer-vs-a-regular-fixed-element\} Her ikisi de içerik kaydırılırken ekranda kalır. İhtiyacınıza uyan seçeneği tercih edin: - **Ekranın ana alt çubuğu için Footer kullanın** (CTA butonu, yasal metin, bağlantılar). Footer kendi yüksekliğini ayırır, bu sayede içerik her zaman onun altına kadar kaydırılabilir ve arkasına gizlenmez; ayrıca alt güvenli alanı otomatik olarak kaplar. - **Kaydırılan içeriğin üzerinde yüzen ya da alt kenar dışında bir kenara sabitlenmesi gereken öğeler için [sabit element](manage-paywall-ui-elements) kullanın** — yüzen kapat/geri yükle butonu, kalıcı üst banner veya en üste kaydır kontrolü gibi. Güvenli alan boşluklarını kendiniz yönetirsiniz. ## Bölücüler \{#dividers\} **Horizontal Divider** ve **Vertical Divider**, içerikleri birbirinden ayıran ince çizgilerdir. Satırları ayırmak için Horizontal Divider'ı, yatay bir kapsayıcı içindeki sütunları ayırmak için ise Vertical Divider'ı kullanın. Kalınlığı, rengi ve uzunluğu sağ panelden ayarlayabilirsiniz. --- # File: using-custom-fonts-in-flow-builder --- --- title: "Flow Builder'da özel fontlar" description: "Flow Builder'a özel font yükleyin ve kullanın." --- Flow oluştururken uygulamanızın geri kalanıyla uyum sağlamak için özel bir font kullanmak isteyebilirsiniz. Özel fontları flow'larınıza nasıl ekleyeceğiniz ve kullanacağınız aşağıda açıklanmıştır. :::tip Flow tasarımına başlamadan önce **Styles** panelinde [fontları yapılandırın](onboarding-text). Bu sayede yapacağınız değişiklikler genel olarak uygulanır. ::: ## Yerleşik fontlar \{#built-in-fonts\} Builder'da bir flow oluşturduğunuzda Adapty, varsayılan olarak sistem fontunu kullanır. Bu genellikle iOS'ta SF Pro, Android'de ise Roboto anlamına gelir; ancak cihaza göre farklılık gösterebilir. Arial, Times New Roman, Courier New, Georgia ve Helvetica gibi yaygın kullanılan fontlar arasından da seçim yapabilirsiniz. Bu fontların her biri birkaç stil seçeneğiyle birlikte gelir. Bu fontlar Adapty SDK'nın bir parçası olarak sunulmaz ve yalnızca önizleme amacıyla kullanılır. Bu fontların tüm cihazlarda mükemmel çalışacağını garanti edemeyiz. Ancak testlerimizde bu fontlar, herhangi ek bir işlem yapmanıza gerek kalmadan çoğu cihaz tarafından tanınmaktadır. Ayrıca [iOS'ta varsayılan olarak hangi fontların mevcut olduğunu kontrol edebilirsiniz](https://developer.apple.com/fonts/system-fonts/). ## Özel yazı tipi ekleme \{#add-a-custom-font\} :::warning Yüklediğiniz dosya **yalnızca editör önizlemesi içindir** — Adapty bunu kullanıcıların cihazlarına göndermez. Yazı tipini cihazda görüntülemek için [dosyayı uygulama paketinenize dahil edin](#add-the-font-files-to-your-apps-bundle). Bu yapılmadan SDK, çalışma zamanında SF Pro (iOS) veya Roboto (Android) ile devam eder. ::: Sistem varsayılanı dışında bir yazı tipi kullanmanız gerekiyorsa özel yazı tipi ekleyebilirsiniz. Özel yazı tipi eklemek için: 0. Eğer font değişken (variable) bir fontsa, benzersiz adlara sahip tek stil dosyalarına bölün. Ağırlık, kalın ve italik kontrolleri özel fontlar için geçerli değildir. Adapty, her özel font dosyası başına yalnızca bir stil kaydeder. [Metni stilize etmek](onboarding-text) için fontu doğru varyasyona geçirin. 1. Herhangi bir font açılır menüsünde **Upload new font** seçeneğini belirleyin. 2. **Add custom font** penceresinde aşağıdaki alanları doldurun: :::warning **Builder'daki font adı**, **iOS font adı** ve **Android font adı**; uygulamadaki tüm özel font dosyalarında benzersiz olmalıdır. ::: - **Font name in Builder**: Builder'da font için bir görünen ad girin. Bu ad, Builder genelindeki font açılır listelerinde görünecektir. - **iOS font name**: Fontun PostScript adını girin. Bunu Font Book → PostScript name kısmında veya [`UIFont` API](https://developer.apple.com/documentation/uikit/uifont) aracılığıyla bulabilirsiniz. - **Android font name**: `res/font/` dizinindeki dosya adını girin. Yalnızca küçük harf, rakam ve alt çizgi kullanın. - **Font file**: Font dosyasını sürükleyip bırakın veya **Select files** düğmesine tıklayın. Desteklenen formatlar: `.ttf`, `.otf`, `.woff`, `.woff2`. 3. **Save font** düğmesine tıklayın. Yazı tipi dosyasını Adapty'ye yükleyerek, bu yazı tipini uygulamanızda kullanma hakkına sahip olduğunuzu onaylamış olursunuz. ### Özel bir yazı tipini silme \{#delete-a-custom-font\} Kontrol panelinden özel bir yazı tipini silmek, taslak ve yayınlanmış tüm flow'lardaki her referansı sessizce sistem yazı tipiyle değiştirir. Herhangi bir uyarı çıkmaz ve bu işlem geri alınamaz. Silmeden önce, hiçbir canlı flow'un o yazı tipini kullanmadığını doğrulayın. ## Flow şablonlarında özel fontlar \{#custom-fonts-in-flow-templates\} [Flow şablon kütüphanesi](paywall-builder-templates), özel fontlar içeren şablonlar sunar. Hangi fontların kullanıldığını görmek için şablon kartındaki **Custom font** etiketinin üzerine gelin. Adapty bu fontları paket içinde sunmaz. Fontları kendiniz temin etmeniz gerekir; etiket üzerinde gösterilen font adlarıyla eşleşen dosyaları bulun. Bazı fontlar ticari lisans gerektirebilir. Font dosyalarını edindikten sonra, aşağıdaki paketleme adımlarını takip edin. ## Font dosyalarını uygulamanızın paketine ekleyin \{#add-the-font-files-to-your-apps-bundle\} Uygulamanızda zaten özel bir font kullanıyorsanız, paywall fontlarınızı da aynı şekilde eklemeniz yeterli. Kullanmıyorsanız, font dosyasını projenize ve uygulamanızın paketine dahil ettiğinizden emin olun. Nasıl yapılacağını aşağıda okuyabilirsiniz: - iOS'ta: [Apple'ın resmi belgelerinde](https://developer.apple.com/documentation/uikit/adding-a-custom-font-to-your-app) - Android'de: [Android'in resmi belgelerinde](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml) --- # File: paywall-head-picture --- --- title: "Arka Planlar" description: "Flow Builder'da bir ekranı düz renk, gradyan, resim veya video arka planıyla doldurun." --- Herhangi bir ekrana arka plan eklemek için [**Screen settings**](paywall-layout-and-products#screen-settings) altındaki **Fill** panelini kullanın. Dört arka plan türü arasından seçim yapın: düz renk, gradyan, resim veya video. ## Resim \{#image\} `.JPG`, `.PNG`, `.GIF` veya `.WEBP` formatında, 20 MB'a kadar bir dosya yükleyin. Resim, tüm arka planı kaplayacak şekilde ölçeklenir. :::note Arka plan resimleri ve videoları, **Safe area** etkin olsa bile çentik ve sistem çubukları arkasındaki alanlar dahil tüm görünüm alanını kaplar. Kırpılmayı önlemek için önemli içerikleri kenarlardan uzak tutun. ::: Arka plan resmini çalışma zamanında uygulama kodunuzdan değiştirmek için [özel medya kimliği](custom-media#custom-media-id) özelliğini etkinleştirin. ## Video \{#video\} `.MP4` veya `.WEBM` formatında, 50 MB'a kadar bir dosya yükleyin. Önizleme sabit bir kare gösterir; ancak video, cihazda çalışma zamanında oynatılır. Videoyu sürekli tekrar oynatmak için **Loop** seçeneğini açın. Arka plan videosunu çalışma zamanında değiştirmek için [özel medya kimliği](custom-media#custom-media-id) özelliğini etkinleştirin. ## Düz renk \{#solid-color\} Bir hex değeri girin ve opaklığı 0 ile 100% arasında ayarlayın. Marka renginizi uygulamak için renk paletinden kayıtlı bir [renk stili](builder-styling) seçin; arka plan, açık ve koyu temalarınızı otomatik olarak takip eder. ## Gradyan \{#gradient\} Çok duraklı doğrusal bir gradyan oluşturun: - **Direction** — Gradyanı 0 ile 360° arasında döndürün. - **Stops** — Yeniden konumlandırmak için çubuk üzerinde sürükleyin. Bir durağın hex değerini ve opaklığını düzenlemek için tıklayın. --- # File: custom-media --- --- title: "Görseller, videolar ve ikonlar" description: "Flow Builder'da bir ekrana görsel, video ve ikon öğeleri ekleyin ve özel medya ID'leriyle çalışma zamanında medyayı değiştirin." --- Flow Builder, **Media** kategorisi altında üç medya öğesi türü içerir: Image, Video ve Icon. :::tip Bir resim veya videoyu — çentik ve ana ekran göstergesi gibi alanlar dahil — tüm ekranı kaplayacak şekilde göstermek için, onu sabit olarak konumlandırın, tüm offset değerlerini 0 yapın ve **Ignore safe area** seçeneğini işaretleyin. Daha fazla bilgi için [Yerleşim ve konumlandırma](manage-paywall-ui-elements#ignore-safe-area) bölümüne bakın. ::: ## Görsel \{#image\} `.JPG`, `.PNG` veya `.GIF` formatında, 20 MB'a kadar dosya yükleyin. - **Aspect** — görselin kapsayıcısına nasıl sığacağını belirler: - **Fit** — görseli kırpmadan kapsayıcının içine sığacak şekilde ölçekler. - **Fill** — görseli kapsayıcıyı dolduracak şekilde uzatır. - **Cover** — görseli kapsayıcıyı kaplayacak şekilde ölçekler, gerekirse kırpar. Varsayılan. - **Use custom media ID** — aşağıdaki [Özel medya ID'si](#custom-media-id) bölümüne bakın. ## Video \{#video\} Maksimum 50 MB boyutunda ve 30 saniyeyi aşmayan bir `.MP4` veya `.WEBM` dosyası yükleyin. Minimum video çözünürlüğü 640x640 pikseldir. - **Aspect** — Fit, Fill veya Cover. Varsayılan değer Fill'dir. - **Loop** — videoyu sürekli tekrarlar. Varsayılan olarak açıktır. - **Use custom media ID** — aşağıdaki [Custom media ID](#custom-media-id) bölümüne bakın. Videolar editör önizlemesinde oynatılmaz; canvas yalnızca sabit bir kare gösterir. Cihazda çalışma zamanında video varsayılan olarak sessiz oynatılır. Loop açıkken süresiz olarak tekrar eder. ### Video bittiğinde bir eylem tetikleme \{#trigger-an-action-when-the-video-ends\} :::link Ana makale: [Eylemler](onboarding-actions) ::: Video öğesi, video sona erdiğinde tetiklenen bir **On playback finished** tetikleyicisini destekler. Başka bir ekrana geçmek, bir CTA göstermek veya başka herhangi bir eylem çalıştırmak için bunu **Interactions** panelinde ayarlayın. ## İkon \{#icon\} Binlerce ikonu iki görsel stilde sunan yerleşik [Tabler Icons](https://tabler.io/icons) kütüphanesinden seçin: - **Stroke** — yalnızca dış hat. - **Filled** — düz dolgu. Bir ikon bulmak için seçicide anahtar kelimeyle arama yapın. İkonun rengini **Color** seçicisinde ayarlayın — kayıtlı bir [renk stili](builder-styling) seçin ya da özel bir renk belirleyin. ## Özel medya kimliği \{#custom-media-id\} :::important Bir resim ve video [arka planı](paywall-head-picture) için de özel medya kimliği ayarlayabilirsiniz. ::: Bir resim veya video öğesine özel medya kimliği ekleyerek uygulama kodunuzdan çalışma zamanında değiştirebilirsiniz. Bunu [kişiselleştirilmiş görseller](get-pb-paywalls#customize-assets) için kullanın — örneğin kullanıcının seçtiği avatarı göstermek gibi. Flow Builder'a yüklediğiniz medya, yedek olarak kullanılır. Kodunuz çalışma zamanında bu kimlik için medya sağlamazsa, bunun yerine yedek gösterilir. Bir Resim veya Video öğesinde özel medya kimliğini etkinleştirmek için: 1. Yükleme alanının altındaki **Use custom media ID** onay kutusunu işaretleyin. 2. Bir medya kimliği girin. 3. Yedek bir görsel veya video yükleyin. Uygulama kodunuzda medyayı kimliğiyle çekmek için SDK API'sine bakın — [Varlıkları özelleştirme](get-pb-paywalls#customize-assets). --- # File: paywall-buttons --- --- title: "Flow builder'daki düğmeler" description: "Flow Builder'da eylem düğmeleri ekleyin ve yapılandırın." --- :::info Bu bölüm, Adapty SDK'larının 4.0 veya daha yüksek sürümleriyle çalışan yeni Flow Builder'ı açıklamaktadır. ::: Butonlar, Flow Builder'daki kullanıcı dokunuşlarına tepki veren etkileşimli öğelerdir. Şu amaçlarla kullanın: - Ürünlere bağlanan ve işlemleri otomatik olarak gerçekleştiren satın alma CTA'ları - Gezinme — kullanıcıları ekranlar arasında taşıma (İleri, Geri, Kapat, Geç) - Yardımcı bağlantılar — Satın Alımları Geri Yükle, Kullanım Koşulları ve Gizlilik Politikası :::tip Satın alma CTA'larını, geri yükleme bağlantılarını ve yasal bağlantıları bir [Footer](builder-containers#footer) içine yerleştirin — bu öğe ekranın alt kısmına sabitlenir ve altında kayan öğeleri örter. ::: ## Buton ekleme \{#add-buttons\} Herhangi bir buton eklemek için: 1. **+** simgesine tıklayın ve **Button** seçeneğini seçin. 2. Bir buton türü seçin. <img src="/assets/shared/img/button-type.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Satın alma düğmeleri, bağlantılar ve kapatma düğmeleri önceden yapılandırılmış eylemlerle gelir. Bağlantılar için [kullanıcıları yönlendirmek üzere URL'leri yapılandırın](#links). Diğer düğme türleri için **Interactions** paneline gidin. Orada, **Button triggers** bölümünde, düğmenin gerçekleştirmesi gereken [eylemleri](onboarding-actions) ayarlayın. <img src="/assets/shared/img/button-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Design** panelinde [buton tasarımını](builder-styling) yapılandırın. ## Buton türleri \{#button-types\} ### Satın alma düğmeleri \{#purchase-buttons\} :::link Satın alma düğmelerinin çalışması için ürünleri ekranlara bağlayın ve **Products** öğesini ekleyin. [Rehbere](paywall-product-block) bakın. ::: Satın alma düğmesi, kullanıcının ekranda seçtiği ürün için uygulama içi satın alma işlemini başlatır. SDK işlemi otomatik olarak yönetir, dolayısıyla uygulama kodunda satın almaları ayrıca ele almanız gerekmez. Satın alma düğmesi eklemek için: 1. **+** düğmesine tıklayın ve **Button** seçeneğini seçin, ardından bir buton ön ayarı seçin. 2. Butonu seçili durumdayken sağ paneldeki **Interactions** sekmesini açın. 3. **Add trigger** > **On tap** seçeneğine tıklayın, ardından **Add action** düğmesine tıklayın. 4. **Action** değerini **Purchase**, **Product** değerini ise `products.selectedProduct` olarak ayarlayın. `products.selectedProduct` değişkeni her zaman ekrandaki o an seçili olan ürüne karşılık gelir. :::tip Satın alma butonlarına animasyon ekleyerek daha fazla dikkat çekebilirsiniz. Paywall Builder şu an için **Pulse** animasyon türünü desteklemektedir. Animasyon stilini **Design** panelinde yapılandırın. ::: <img src="/assets/shared/img/purchase-button.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Bağlantılar \{#links\} :::important **Terms of Use** ve **Privacy Policy** butonlarında yerleşik bir **Open URL** eylemi bulunur. Hedef URL'yi buradan ayarlayın. Boş Open URL'ler ve [satır içi bağlantılar](onboarding-text#inline-link) önizleme ve yayınlamayı engeller. ::: Bazı mağaza gereksinimlerini karşılamak için şunlara bağlantı ekleyebilirsiniz: - Kullanım koşulları - Gizlilik politikası - Satın alma geri yükleme Bağlantı eklemek için: 1. **+** butonuna tıklayın ve **Button > Links** seçeneğini seçin. Bu işlem, önceden tanımlanmış aksiyonlara sahip bir satır içi buton grubu ekler: satın almaları geri yükleme veya bir URL açma. Dahil edilen butonların tamamına ihtiyaç duymuyorsanız, gereksiz olanları katmanlar panelinden silin. <img src="/assets/shared/img/add-links.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şimdi buton eylemlerini ayarlayın: - **Restore purchases** butonu satın alma geri yüklemelerini zaten yönetiyor. - Kalan her bağlantı için: 1. Seçmek için butona tıklayın ve sağdaki **Interactions** sekmesine geçin. 2. URL'yi alana yapıştırın. 3. Varsayılan olarak URL, kesintisiz bir kullanıcı deneyimi için uygulama içi tarayıcıda açılır. Kullanıcıları harici bir tarayıcıya yönlendirmek istiyorsanız **Open in external browser** onay kutusunu işaretleyin. <img src="/assets/shared/img/pb-links.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Flow'u kapat \{#close-flow\} **Close** düğmesi flow'u otomatik olarak kapatır. Kapat düğmesi eklemek için **+** simgesine tıklayın ve **Button > Close flow** seçeneğini seçin. <img src="/assets/shared/img/close-flow.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::tip Kapat düğmesini ekranın köşesine yerleştirmek için **Absolute** konumlandırmayı kullanın. ::: Ayrıca [eylemler](onboarding-actions) aracılığıyla herhangi bir düğmeyi flow'u kapatacak şekilde yapılandırabilirsiniz. ### Özel düğmeler \{#custom-buttons\} Eklediğiniz herhangi bir düğme, dokunulduğunda şu eylemlerden birini gerçekleştirecek şekilde yapılandırılabilir: - Sonraki ekrana git - Uyarı göster - [Değişken](onboarding-variables) ayarla - [Ekran öğelerini göster veya gizle](onboarding-element-visibility) - URL aç - Satın almaları geri yükle - Koşullu eylemler gerçekleştir --- # File: builder-tabs --- --- title: "Sekmeler" description: "Bir flow'da içerik panellerini değiştiren sekme navigasyonu ekleyin." --- **Sekmeler**, bir ekran bölümünü birbirini değiştiren içerik panellerine böler — kullanıcı bir sekme başlığına dokunur ve aşağıdaki panel buna göre güncellenir. {/* TODO: on-device GIF */} ## Sekme ekleme, silme ve seçme \{#add-remove-and-select-tabs\} Her sekme iki bölümden oluşur: - **Sekme başlığı** — tıklanabilir etiket (Tab 1, Tab 2 vb.). - **Sekme içeriği** — her sekme için bir içerik alanı. İçerik alanına eklediğiniz her şey, ilgili sekme seçildiğinde görünür. Yeni sekme eklemek için **Add tab** düğmesine tıklayın. Her yeni sekme için otomatik olarak bir içerik alanı oluşturulur. Ekran ilk açıldığında belirli bir sekmenin aktif olmasını istiyorsanız **Selected by default** seçeneğini etkinleştirin. ## Sekmeleri Stillendirme \{#style-the-tabs\} ### Şablonlar \{#templates\} Flow Builder, kullanıma hazır üç sekme şablonu sunar: - **Segment control** — seçili sekmenin etrafında yuvarlak köşeli, hap şeklinde bir geçiş elemanı. - **Button Tabs** — ayrı buton stilli sekmeler. - **Underline** — seçili sekmeyi alt çizgiyle işaretleyen metin etiketleri. ### Sekme durumları \{#tab-states\} Her sekmenin kendi durum değiştirici düğmesi vardır (**Default / Selected**); bu sayede aktif ve pasif durumları ayrı ayrı biçimlendirebilirsiniz — her durum için tipografi, renkler, dolgu ve kenarlık. ## Seçilebilir grup \{#selectable-group\} Sekmeler, **tek seçimli bir seçilebilir grup** oluşturur — her seferinde yalnızca bir sekme aktif olabilir. Grubu, **Screen settings** panelindeki [Selectable groups](paywall-layout-and-products#selectable-groups) bölümünden yönetebilirsiniz. Grup iki değişken sunar: - `tabs.selectedOptionId` — seçili sekmenin ID'si. Koşullarda kullanabilirsiniz. - `tabs.selectedOptionTitle` — seçili sekmenin etiketi. Dinamik metinlerde kullanabilirsiniz. Grubu yeniden adlandırdıysanız `tabs` ifadesini kendi özel **Group ID** değerinizle değiştirin. Tam bilgi için [Seçilebilir öğeler ve gruplar](flow-selectable-elements) bölümüne bakın. --- # File: builder-toggles --- --- title: "Toggle'lar" description: "Ödeme akışlarınıza toggle anahtarları ekleyin." --- :::warning Apple, önceden seçili deneme toggle'ı kullanan uygulamaları reddedebilir. Varsayılan olarak "açık" konumda ayarlanmış bir toggle, App Store İnceleme Yönergeleri kapsamında yanıltıcı bir karanlık kalıp olarak işaretlenebilir; bu durum, kullanıcının açık bir seçim yapmaksızın ücretsiz denemeye onay verdiği izlenimini yaratır. Reddedilmemek için toggle'ı varsayılan olarak **kapalı** konuma getirin ve kullanıcıların denemeyi kendilerinin etkinleştirmesine izin verin. ::: Deneme geçişi, kullanıcıların bir paywall üzerinde standart ve deneme tabanlı ürünler arasında seçim yapmasını sağlayan iki durumlu bir anahtardır. Kullanıcı bu anahtarın durumunu değiştirdiğinde, ürün gruplarını değiştirme, değişkenleri güncelleme ya da öğeleri gösterip gizleme gibi işlemler anında tetiklenebilir. Deneme geçişi eklemek için hedef ekranda **+** simgesine tıklayın ve **Trial toggle** seçeneğini seçin. Her deneme geçişi, **Toggle** türünde seçilebilir bir öğedir. Her seçilebilir öğeye, durumunu yansıtmak için bir değişken atanır; örneğin `trial` adlı bir geçişe `True` veya `False` değeri alan bir `trial.is_selected` değişkeni atanır. Diğer öğeleri toggle durumuna bağlı kılmak için bu değişkeni temel alarak koşullu bir [eylem](onboarding-actions) veya [koşullu görünürlük](onboarding-element-visibility) ayarlayın. --- # File: builder-reviews-and-testimonials --- --- title: "Yorumlar ve referanslar" description: "Bir paywalla incelemeler, puanlamalar ve sosyal kanıt ekleyin." --- **User Engagement** element kategorisi, bir paywallda yorumları, puanlamaları ve sosyal kanıtları sergilemek için dört şablon sunar. Her şablon tam olarak düzenlenebilir bir kompozisyondur — yer tutucu metni değiştirin ve flow'un geri kalanıyla uyumlu hale getirmek için [renk stillerinizi](builder-styling) ve [tipografinizi](onboarding-text) uygulayın. ## İnceleme \{#review\} Tek bir derecelendirme, alıntı ve yazar bilgisi içeren bir kart. Unutulmaz bir kullanıcı alıntısını öne çıkarmak için kullanın. ## Derecelendirme \{#rating\} Yıldız satırı ve sayıyı birlikte gösteren bir bileşen; örneğin "17000+ değerlendirme". Değerlendirme hacmini vurgulamak için kullanılır. ## Uygulama Puanı \{#app-rating\} Örnek boyutuyla birlikte öne çıkan bir puan gösterimi; "4.9 / 1000'den fazla değerlendirmeye dayanarak" gibi. Güçlü bir genel puanı vurgulamak için kullanın. ## Sosyal Kanıt \{#social-proof\} Üye sayısıyla birlikte bir avatar grubu, örneğin "50.000'den fazla kullanıcıya katıl". Topluluk büyüklüğünü vurgulamak için kullanın. --- # File: flow-timer --- --- title: "Geri sayım sayacı" description: "Bir paywall'a geri sayım sayacı ekleyin." --- **Geri sayım sayacı**, belirli bir süreden geriye doğru sıfıra kadar sayar — sıfıra ulaştığında ekran dondurulur. ## Şablonlar \{#templates\} Bu kategori dört görsel varyant sunar: - **Blocks** — Gün, saat, dakika ve saniye ayrı etiketli hücrelerde gösterilir. - **Inline Units** — Birim son ekleriyle tek satırlık metin. - **Inline** — Yalnızca rakamlar. - **Badge** — Hap şeklinde rakam gösterimi. ## Ayarlar \{#settings\} ### Süreyi ayarlayın \{#set-the-duration\} Sağ panelin **Countdown** bölümüne başlangıç süresini gün, saat, dakika ve saniye cinsinden girin. ### Davranışı yapılandırma \{#configure-the-behavior\} **Behavior** açılır menüsü, zamanlayıcının ne zaman başlayacağını belirler: - **Every appear** — Kullanıcı ekranı her açtığında yeniden başlar. Varsayılan. - **First appear** — Geçerli uygulama oturumunda kullanıcının ekranı ilk görüntülemesiyle başlar. Aynı oturumda geri dönüldüğünde saymaya devam eder; uygulama yeniden başlatıldığında sıfırlanır. - **First appear (persisted)** — Kullanıcının ekranı ilk açmasıyla başlar ve uygulama yeniden başlatılsa da saymaya devam eder. ### Zamanlayıcı sona erdiğinde bir eylem tetikleyin \{#trigger-an-action-when-the-timer-ends\} :::link Ana makale: [Eylemler](onboarding-actions) ::: Geri sayım sıfıra ulaştığında bir eylem çalıştırmak için **On timer end** tetikleyicisi ekleyin — örneğin, başka bir ekrana geçin veya indirim rozetini gizleyin. --- # File: onboarding-quizzes --- --- title: "Flow'larda sınavlar" description: "Kullanıcı tercihlerini toplamak ve kişiselleştirilmiş flow'lar oluşturmak için Adapty flow'larınıza interaktif sınavlar ekleyin — kod yazmanıza gerek yok." --- Kullanıcılara önceden tanımlanmış seçenekler sunmak için sınavları kullanın. Input'ların aksine, sınavlarda yazı yazılan alanlar bulunmaz — kullanıcılar sizin belirlediğiniz seçenekler arasından tercih yapar. Tercihleri toplamak, kullanıcıları segmentlere ayırmak veya verdikleri cevaplara göre flow'u dallandırmak için bunları kullanabilirsiniz. ### Bir test ekleyin \{#add-a-quiz\} 1. Sol üstteki **+** simgesine tıklayın. 2. **Quiz** seçeneğini belirleyin. 3. Test türünü seçin: - **Icon/image/emoji options:** Her seçeneğin yanında bir ikon, resim veya emoji ile metin etiketi bulunan dikey bir liste. - **Icon/image/emoji grid:** Her seçeneğin ikon, resim veya emoji içerdiği bir ızgara düzeni. - **Rating:** Kullanıcıların sayısal veya yıldız tabanlı olarak puan verebileceği bir ölçek. ### Koşullu yönlendirme kurulumu \{#set-up-conditional-navigation\} Kullanıcıları seçimlerine göre farklı yönlendirmek için koşullu eylemi sınav seçeneğine değil, **gezinti düğmesine** ayarlayın: 1. Navigasyon düğmesini seçin. 2. **Interactions** panelinde, **Conditional** eylemli bir **On Tap** tetikleyicisi ekleyin. 3. **Edit Action** iletişim kutusunda **if** satırını oluşturun: - Sol tarafta `{}` simgesine tıklayın ve kullanıcının seçimini referans almak için **Elements → Screen → `<quizElementId>.selectedOptionId`** seçeneğini belirleyin. - Operatörü `=` olarak bırakın. - Sağ tarafta, eşleştirilecek elementId'yi girin — örneğin `rock`. 4. **then** altında, eylemi **Navigate to** olarak ayarlayın ve hedef ekranı seçin. 5. **else** altında, bir yedek **Navigate to** hedefi belirleyin veya diğer seçenekler için daha fazla koşul eklemek üzere **+ Add else/if** seçeneğine tıklayın. :::link Quiz yanıtlarını nasıl kullanacağınızı anlamak için ilgili kılavuzlara bakın: - [Koşullu gezinme](onboarding-navigation-branching) - [Değişkenler](onboarding-variables) - [Eylemler](onboarding-actions) ::: ### Test türünü değiştirin \{#change-quiz-type\} Varsayılan olarak bir test **multi choice** şeklindedir — kullanıcılar aynı anda birden fazla seçenek belirleyebilir. Kullanıcıların yalnızca bir seçenek seçmesini istiyorsanız **single choice** moduna geçin. 1. Testi içeren ekranı seçin. 2. **Screen settings** bölümünde **Selectable groups** kısmına kaydırın ve testinize tıklayın. 3. **Edit group** iletişim kutusunda **Group type** seçeneğini açın ve şunlardan birini seçin: - **Single choice** — aynı anda yalnızca bir seçenek belirlenebilir. - **Multi choice** — kullanıcılar birden fazla seçenek belirleyebilir. 4. **Save** düğmesine tıklayın. --- # File: builder-inputs-and-forms --- --- title: "Flow Builder'da girişler ve formlar" description: "Metin alanları ve onay kutuları gibi etkileşimli form öğeleri ekleyin." --- Kullanıcılardan ad, e-posta adresi veya doğum tarihi gibi yazılı veri toplamak için girişleri kullanın. Yanıtları saklayın ve sonraki ekranlarda kullanıcıya adıyla hitap etmek gibi amaçlarla flow'un farklı yerlerinde bunlara başvurun. ## Bir girdi ekle \{#add-an-input\} 1. Sol üstteki **+** simgesine tıklayın. 2. **Input** seçeneğini seçin. 3. Girdi türünü belirleyin: - **Text:** Kısa metin girişleri için. - **Email:** E-posta adresleri; isteğe bağlı format doğrulaması ile. - **Password:** Güvenli metin girişi; yapılandırılabilir gereksinimler ile. - **Number:** Sayısal değerler; yapılandırılabilir format ile. - **Phone number:** Telefon numaraları. - **Date:** Tarih seçici açar. - **Time:** Saat seçici açar. - **Date and time:** Birleşik bir seçici açar. ## Girdi yapılandırma \{#configure-an-input\} :::link Görsel ayarlar — düzen, stil ve görünürlük — hakkında daha fazla bilgi için [Stiller ve görünüm](builder-styling) bölümüne bakın. ::: Tüm girdi türleri için **Design** sekmesinde şunları yapılandırabilirsiniz: - **Type:** Giriş türünü değiştirin (Text, Email, Password, Number, Phone number, Date, Time veya Date and time). - **Element ID:** Giriş değerini flow içinde başka yerlerde referans almak için kullanılan tanımlayıcı. Aşağıdaki [Giriş değerlerini kullanma](#use-input-values) bölümüne bakın. - **Placeholder:** Boş alanda görüntülenen ipucu metni. - **State:** Girişin farklı durumlarda nasıl göründüğünü tanımlayın. **Default**, **Active**, **Invalid** ve **Disabled** arasında geçiş yaparak her birine farklı görsel uygulayın. - **Typography:** Alanda görüntülenen değerin metin stili. - **Leading and trailing icons:** Giriş alanının içine simge ekleyin. Bazı ayarlar yalnızca belirli girdi türlerine özgüdür: | Ayar | Giriş türleri | |---|---| | Temizle düğmesi | Metin, E-posta | | E-posta formatını doğrula | E-posta | | Şifre göster simgesi | Şifre | | Şifre gereksinimlerini düzenle | Şifre | | Sayı formatı | Sayı | | Tarih/saat formatı | Tarih, Saat, Tarih ve saat | | Min ve maks tarih | Tarih, Tarih ve saat | ## Girdi değerlerini kullanma \{#use-input-values\} Her girdi, otomatik olarak bir değişken olarak kullanılabilir — herhangi bir kurulum ya da **On Submit** eylemi gerekmez. Değer, **Input Settings** bölümünde belirlediğiniz **Element ID** üzerinden referans alınır. Bir girdi değerini flow'un başka bir yerinde kullanmak için (örneğin, metni kişiselleştirmek, başka bir alanı doldurmak veya koşullu gezinmeyi yönlendirmek amacıyla) bir değişken ekleyin ve şunu seçin: **Element > Screen > `<elementId>.value`** :::link İlgili kılavuzları inceleyerek kaydedilen giriş değerlerini nasıl kullanacağınızı öğrenin: - [Koşullu navigasyon](onboarding-navigation-branching) - [Değişkenler](onboarding-variables) ::: ## Girdi doğrulama \{#input-validation\} Doğrulama davranışı girdi türüne göre değişir. Her girdi, girilen değerin doğrulama kurallarını karşılayıp karşılamadığını gösteren salt okunur bir Boolean değişkeni olan `<elementId>.isValid`'i kullanıma sunar. Bunu koşullu eylemlerde veya koşullu görünürlükte kullanabilirsiniz — örneğin, bir e-posta formatı geçerli olana kadar İleri düğmesini gizlemek için. :::note - `isValid` değişkeni salt okunurdur — bu değişkeni siz ayarlayamazsınız. - Boş bir girdi her zaman geçerli kabul edilir. - Metin girdilerinin doğrulama kuralı yoktur. `textInput.isValid` her zaman `True` döndürür. ::: | Girdi türü | Doğrulama davranışı | |---|---| | Metin | Yerleşik doğrulama kuralı yoktur. | | E-posta | İsteğe bağlı. Girilen değeri e-posta formatına göre kontrol etmek için **Design** panelinde **Validate email format** seçeneğini etkinleştirin. | | Telefon numarası | Yerleşik telefon numarası format kontrolü. Builder'da yapılandırılamaz — kural çalışma zamanında değerlendirilir. | | Şifre | Yapılandırılabilir. Aşağıdaki [Şifre gereksinimleri](#password-requirements) bölümüne bakın. | | Sayı | Format tabanlı. Girilen değer, seçilen sayı formatıyla eşleşmelidir. Aşağıdaki [Sayı formatı](#number-format) bölümüne bakın. | | Tarih, Saat, Tarih ve saat | Yerleşik. Seçici yalnızca geçerli tarih veya saat değerlerini kabul eder. | **Geçersiz** [görsel durum](builder-styling#input-states), kullanıcı formu gönderdiğinde — örneğin klavyeden Enter veya Done tuşuna bastığında — etkinleşir. O ana kadar input, **Aktif** veya **Varsayılan** durumu gösterir. ### Şifre gereksinimleri \{#password-requirements\} Şifre girişleri, yapılandırılabilir doğrulama kurallarını destekler. Kural düzenleyicisini açmak için **Design** panelindeki **Edit password requirements** seçeneğine tıklayın. Etkinleştirilen kurallar, girişin altında canlı bir kontrol listesi olarak görüntülenir; her kural karşılanır karşılanmaz yanında bir onay işareti belirir. Kullanılabilir kurallar: - **Min length** — minimum karakter sayısı. Varsayılan: 8. - **Max length** — maksimum karakter sayısı. Varsayılan: 32. - **Uppercase letter** — en az bir A–Z karakteri. - **Lowercase letter** — en az bir a–z karakteri. - **Number** — en az bir rakam. - **Special character** — en az bir alfanümerik olmayan karakter (örneğin, `!@#$%`). Şifre yalnızca etkinleştirilen tüm kurallar sağlandığında geçerli sayılır. ### Sayı biçimi \{#number-format\} **Number** giriş ayarlarındaki **Format** açılır menüsü, girilen değerin nasıl ayrıştırılacağını belirler: - **Integer** — yalnızca tam sayılar (örneğin, `4`). - **Decimal (Point)** — ayraç olarak nokta kullanan ondalıklı sayılar (örneğin, `4.89`). - **Decimal (Comma)** — ayraç olarak virgül kullanan ondalıklı sayılar (örneğin, `4,89`). Seçilen biçimle eşleşmeyen değerler geçersiz sayılır. ## Girdi olaylarında eylemleri tetikleme \{#trigger-actions-on-input-events\} :::link Ana makale: [Eylemler](onboarding-actions) ::: **Interactions** paneli aracılığıyla kullanıcının girdisine tepki olarak eylemler çalıştırabilirsiniz: - **On changed** — kullanıcı girdinin değerini değiştirdiğinde tetiklenir. Tüm girdi türlerinde kullanılabilir. - **On submit** — kullanıcı klavyedeki Enter veya Done tuşuna basarak bir metin girdisini gönderdiğinde tetiklenir. Tarih ve saat seçicilerinde bu tetikleyici bulunmaz. --- # File: onboarding-navigation-branching --- --- title: "Navigasyon ve dallanma" description: "Kullanıcıları ekranlar arasında statik rotalar ve dinamik dallanma kullanarak yönlendirin." --- Navigasyon ve dallanma, kullanıcıları flow'unuzun her adımında yönlendirmenizi sağlar: herkesi temel ekranlara göndermek için statik rotalar, kullanıcı tercihlerine göre flow'u uyarlamak için dinamik navigasyon kullanın. :::link Navigasyon bir aksiyon türüdür. Aksiyonlar hakkında daha fazla bilgi edinmek için [Aksiyonlar](onboarding-actions) sayfasına bakın. ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/OLl-WziDMhU?si=_eUtsmbEuFAaLj1r" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## Ekranlar arasında gezinme \{#navigate-between-screens\} Farklı flow öğelerini kullanarak statik ve dinamik gezinme yapılandırabilirsiniz. ### Statik gezinme \{#static-navigation\} Statik gezinme, tüm kullanıcıları aynı hedef ekrana yönlendirir. Bunu ayarlamak için: 1. Kullanıcıların dokunabileceği herhangi bir öğeyi seçin — düğme, quiz cevabı veya geçiş. 2. Sağdaki **Interactions** panelini açın. Ardından **Add trigger** seçeneğine tıklayın. Kullanıcıları bir quiz seçeneğine dokundukları anda yönlendirmek için — ayrı bir düğmeye dokunmalarına gerek kalmadan — burada bir düğme yerine quiz seçeneği öğesini seçin. 3. **On tap** tetikleyicisini ayarlayın: - **Action**: **Navigate to screen** seçeneğini seçin. - **Destination**: Hedef ekranı belirleyin. ### Dinamik Navigasyon \{#dynamic-navigation\} Dinamik navigasyon, kullanıcıları quiz cevaplarına, toggle öğelerinin durumuna ve özel niteliklere göre yönlendirir. [Seçilebilir öğeler](flow-selectable-elements) dinamik navigasyon için birer koşul olarak kullanılabilir. Kurulum için: 1. Kullanıcıları yönlendirecek öğeyi seçin. 2. Sağdaki **Interactions** panelini açın ve **Add trigger** seçeneğine tıklayın. Kullanıcıları ayrı bir buton tıklamasına gerek kalmadan, bir quiz seçeneğine dokundukları anda yönlendirmek istiyorsanız — buton yerine quiz seçeneği öğesini seçin. 3. **On tap** tetikleyicisini ayarlayın: - **Action**: **Conditional** seçeneğini belirleyin. - **Conditions**: Koşullu gezinme eylemlerini ayarlayın. Daha fazla bilgi için [buraya](onboarding-actions#conditional-actions) bakın. ## Flow'u kapatma \{#close-flow\} Kullanıcı yolculuğunuz flow'u kapatmayı gerektiriyorsa, bunu butonlar veya tek cevaplı testler aracılığıyla ayarlayabilirsiniz: 1. Dokununca flow'u kapatması gereken bir element ekleyip seçin. 2. Sağ taraftaki **Interactions** panelini açın. Ardından **Add trigger** seçeneğine tıklayın. 3. **On tap** tetikleyicisini ayarlayın: - **Action**: **Close flow** seçeneğini seçin. --- # File: onboarding-actions --- --- title: "Eylemler" description: "Kullanıcı etkileşimleriyle tetiklenen eylemleri builder'da tanımlayın." --- **Interactions** (Etkileşimler) paneli, flow öğelerinin olaylara — dokunma, öğe görünümü ve form gönderme gibi — nasıl tepki vereceğini tanımlamanıza olanak tanır. Her olay için bir veya daha fazla eylem atayabilirsiniz: ekranlar arasında gezinme, öğeleri gösterme veya gizleme, URL açma, değişken ayarlama ve daha fazlası. Kullanıcı verilerine göre flow'u özelleştirmek için koşullar kullanın. Her etkileşim üç bölümlü bir zinciri takip eder: 1. **Element**: Etkileşimi başlatan ekran bileşeni — bir düğme, sınav yanıtı, giriş alanı veya başka herhangi bir şey. 2. **Trigger**: Mantığı etkinleştiren olay; örneğin bir dokunma, bir öğenin görünmesi veya form gönderimi. 3. **Action**: Flow'un yanıt olarak gerçekleştirdiği görev. Tek bir tetikleyici, sırayla birden fazla action çalıştırabilir. ## Etkileşimleri ayarlama \{#set-up-interactions\} Bir etkileşim ayarlamak için: 1. Ekranda veya **Layers** panelinde bir öğe seçin. 2. Sağda **Interactions** paneline geçin ve **Add trigger** düğmesine tıklayın. 3. **Button triggers** bölümünde [tetikleyici türünü](#trigger-types) seçin. 4. **Add action** düğmesine tıklayın, aksiyon adına tıklayın ve **Edit action** penceresindeki açılır menüden bir [aksiyon türü](#action-types) seçin. 5. Seçtiğiniz [aksiyon türüne](#action-types) göre aksiyon özelliklerini yapılandırın. 6. Gerekirse aynı tetikleyici için daha fazla aksiyon eklemek üzere **Add action** düğmesine tıklayın. ## Tetikleyici türleri \{#trigger-types\} Tetikleyiciler, kullanıcı davranışına, öğe durum değişikliklerine veya ekranın yüklenmesine yanıt olarak çalışır. **On screen appear** evrenseldir; diğerleri ise öğeye özgüdür. | Tetikleyici | Ne zaman çalışır... | Desteklenen öğeler | |---|---|---| | **On screen appear** | Ekran yüklendiğinde | Tüm öğeler | | **On tap** | Kullanıcı öğeye dokunduğunda | [Düğmeler](paywall-buttons), [quiz seçenekleri](onboarding-quizzes), [geçiş düğmeleri](builder-toggles), [geri sayımlar](flow-timer), [videolar](custom-media) | | **On changed** | Kullanıcı girişin değerini değiştirdiğinde (yazma, tarih veya saat seçme) | Tüm [giriş öğeleri](builder-inputs-and-forms) | | **On submit** | Kullanıcı klavyede Enter veya Done tuşuna basarak metin girişini gönderdiğinde | [Metin tabanlı girişler](builder-inputs-and-forms) | | **On timer end** | Bir [Geri Sayım](flow-timer) öğesi sıfıra ulaştığında | [Geri Sayım](flow-timer) | | **On playback finished** | Bir [Video](custom-media) sonuna ulaştığında | [Video](custom-media) | Yerleşik etkileşimleri olmayan öğeler (örneğin [Loader](builder-loaders-and-progress-bars)) için yalnızca **On screen appear** tetikleyicisi kullanılabilir. ## Eylem türleri \{#action-types\} :::important **Kullanıcıyı farklı bir ekrana götüren her türlü gezinme eylemi**, listede her zaman son eylem olmalıdır. Ekran değiştiğinden, bundan sonra eklenen eylemler ("Set Variable" gibi) çalışmayabilir. ::: ### Ekrana git \{#navigate-to-screen\} Bu, kullanıcıları ekranlar arasında taşımak için kullanılan temel eylemdir. Kullanıcıyı belirtilen hedef ekrana yönlendirir. Bu eylem için yalnızca hedef ekranı ayarlamanız gerekir. Dinamik navigasyonu etkinleştirmek istiyorsanız [Navigasyon ve dallanma](onboarding-navigation-branching) veya [Koşullu eylemler](#conditional-actions) bölümüne bakın. ### Sonraki ekrana geç \{#navigate-next\} Kullanıcıyı flow'daki ekran sırasında bir sonraki ekrana ilerletir. Bu özelliği, düzenleyicideki ekran sırasının kullanıcılara göstermek istediğiniz sırayla eşleştiği doğrusal flow'lar için kullanın. ### Geri Git \{#navigate-back\} Kullanıcıyı, dizideki önceki ekran yerine, gezinme geçmişindeki önceki ekrana döndürür. ### URL Aç \{#open-url\} :::tip Akan metne bağlantı eklemek için [satır içi bağlantıları](onboarding-text#inline-link) kullanın. ::: Belirli bir web adresini açar. Kullanıcıları uygulamanızın yerel ekranları dışındaki web sayfalarına, makalelere veya sosyal medya profillerine yönlendirmek için kullanın. Bu eylem için iki ayar yapılandırabilirsiniz: - **URL adresi**: Bir URL adresi belirleyin. Bunu dinamik hale de getirebilirsiniz — örneğin, kullanıcıları quiz yanıtlarına veya gönderdikleri verilere göre farklı sayfalara yönlendirmek için. Bunun için Variable icon simgesine tıklayın ve kullanmak istediğiniz değişkeni seçin. - **Harici tarayıcıda aç**: Harici bağlantıların nerede açılacağını belirleyin. Varsayılan olarak, kullanıcıları uygulama içinde tutmak amacıyla uygulama içi tarayıcıda açılırlar. Bağlantıların harici bir tarayıcıda açılmasını istiyorsanız **Open in external browser** onay kutusunu seçin. ### Flow'u kapat \{#close-flow\} Mevcut flow'u kapatır. ### Öğeleri göster/gizle \{#showhide-elements\} Ekrandaki belirli bir öğeyi gösterir veya gizler. Bu eylem, **Design** panelindeki **Visibility** ayarında belirlenen başlangıç durumunu geçersiz kılar. **Visibility** **Hide** olarak ayarlanmışsa, **Show** eylemi öğeyi görünür hale getirir. :::important Hedef öğe seçilmemiş bir **Show** veya **Hide** eylemi [önizleme ve yayınlamayı engeller](builder-save-publish#troubleshooting). Bir hedef seçin ya da eylemi kaldırın. ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/3w3YSOmI3tQ?si=vPhoQGt44SI285Ru" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ### Uyarı göster \{#show-alert\} Yerel bir sistem açılır penceresi görüntüler. Kullanıcıların devam etmek için **Ok** düğmesine dokunması gerekir. Uyarılar için **Title** ve **Message** alanlarını ayarlamanız gerekir. Her iki alanda da içeriği dinamik hale getirmek için değişkenler kullanabilirsiniz. Bunun için Variable icon simgesine tıklayın ve kullanmak istediğiniz değişkeni seçin. :::important Boş veya eksik yapılandırılmış bir **Show alert** eylemi [önizleme ve yayınlamayı engeller](builder-save-publish#troubleshooting). Her iki alanı da doldurun ya da eylemi kaldırın. ::: ### Değişken ayarla \{#set-variable\} Flow'daki bir değişkenin değerini günceller. Bu aksiyonu eklemeden önce soldaki **Variables** panelinde değişkenler oluşturun (bkz. [Değişkenler](onboarding-variables)). **Add variable** seçeneğine tıklayın ve ihtiyacınız kadar değişken ve değer ekleyin. :::important Atama yapılmamış bir **Set variable** aksiyonu [önizleme ve yayımlamayı engeller](builder-save-publish#troubleshooting). En az bir atama yapın ya da aksiyonu kaldırın. ::: ### Satın Alma \{#purchase\} Onboarding'inizdeki bir düğme veya etkileşimden doğrudan satın alma akışını başlatır. Kullanıcıların flow'dan çıkmadan bir ürüne abone olmasına veya ürün satın almasına olanak tanır. Bu eylem için iki farklı davranış yapılandırabilirsiniz: - **Uygulama içi mağaza**: Yerel bir satın alma başlatır. **Product** alanını belirli bir ürüne veya kullanıcının ekranda seçtiği ürün için `products.selectedProduct` değerine ayarlayın. - **Web ödeme**: Yerel bir satın alma tetiklemek yerine kullanıcıyı bir [web paywall](web-paywall)'a yönlendirir. Bunu, işlemi uygulama dışında, örneğin web tabanlı abonelik teklifleri için yönetmek istediğinizde kullanın. :::important **Ürün** veya **Web Paywall URL** hedefi olmayan bir **Purchase** eylemi [önizlemeyi ve yayımlamayı engeller](builder-save-publish#troubleshooting). Bir hedef atayın ya da eylemi kaldırın. ::: ### Satın almaları geri yükle \{#restore-purchases\} Cihazda satın almaları geri yükleme akışını başlatır. Kullanıcılar, daha önce başka bir cihazda abonelik satın aldıklarında veya uygulamayı yeniden yükledikten sonra haklarına yeniden erişmek istediklerinde buna dokunur. Bu eylem için yapılandırılacak herhangi bir şey yoktur — Adapty, geri yükleme işlemini yerel mağaza akışı aracılığıyla gerçekleştirir. **Restore purchases** eylemi, **Links** düğme ön ayarındaki **Restore** bağlantısında da önceden yapılandırılmıştır (bkz. [Satın almaları ayarlama](paywall-product-block#restore-purchases)). ## Özel eylemler \{#custom-actions\} Özel bir eylem, uygulamanızın kendi kodunun işlediği adlandırılmış bir **Action ID** tetikler. Yerleşik eylem türleri ihtiyacınızı karşılamadığında kullanın. Adapty tetikleyiciyi sağlar; davranışı uygulamanız uygular: 1. Builder'da, bir öğenin etkileşimine bir **Action ID** atarsınız. 2. Kullanıcı etkileşimi tetiklediğinde, flow ID'yi uygulamanıza iletir. 3. Uygulamanız ID'yi eşleştirir ve kodunuzu çalıştırır. ### Özel bir eylem ayarlama \{#set-up-a-custom-action\} 1. **Edit action** penceresinde, uygulamanızın tanıyacağı bir dize olan **Action ID**'yi atayın (örneğin, `show_discount`). 2. Uygulama kodunuzda bu Action ID için bir işleyici uygulayın. Uygulama ayrıntıları ve kod örnekleri için [Paywall eylemlerini işleme](handle-paywall-actions) bölümüne bakın. :::important **Action ID** olmayan bir **Custom** eylem, [önizleme ve yayımlamayı engeller](builder-save-publish#troubleshooting). Bir Action ID atayın veya eylemi kaldırın. ::: ### Özel eylemlerle neler yapabilirsiniz \{#what-you-can-do-with-custom-actions\} Özel bir eylemin kendi başına hiçbir işlevi yoktur. Builder'da statik bir Eylem Kimliği (Action ID) tanımlarsınız; bu kimliği aldığında ne olacağını ise uygulama kodunuz belirler. Aşağıdaki her kullanım senaryosu aynı kalıbı izler: flow'da bir kimlik atayın, ardından kodunuzda bu kimliği işleyin. - **Uygulama içi bir etkinlik tetikleyin**: `viewed_special_offer` gibi bir ID tetikleyin, ardından uygulamanız bunu aldığında olayı analytics'e kaydedin. - **Sistem izni isteyin**: `request_location` gibi bir ID tetikleyin, ardından uygulamanızdan OS izin penceresini açın. İznin açılamadığı durumlarda bunun yerine telefonun sistem ayarlarını açın. Adapty pencereyi göstermez — bunu uygulamanız yapar. - **Native kimlik doğrulamayı başlatın**: `login_google` gibi bir ID tetikleyin, ardından kendi giriş ekranınızı gösterin. Flow kullanıcıyı oturum açtıramaz. - **İş mantığı uygulayın**: `apply_discount` gibi bir ID tetikleyin, ardından içeriğin kilidini açın ya da uygulama durumunu kendi tarafınızda değiştirin. - **Bir quiz cevabını uygulamanıza iletin**: Her seçeneğe farklı bir Action ID atayın (örneğin `goal_weight_loss` ve `goal_muscle`), ardından kodunuzda bu ID'yi okuyun. Daha sonra segmentlere ayırabileceğiniz bir [özel kullanıcı özelliği](setting-user-attributes#custom-user-attributes) ayarlamak için bu ID'yi kullanın. Aksiyon yalnızca sabit bir ID taşıdığından, seçimi bildirmenin tek yolu budur — flow seçilen değeri gönderemez. :::important Özel bir action, kullanıcı bir seçenek belirlediği anda tetiklenir. Kullanıcı cevabını değiştirirse flow, yeni Action ID'yi de tetikler. Uygulamanız her ikisini sırayla alır — örneğin önce `goal_weight_loss`, ardından `goal_muscle`. Handler'ınızı idempotent yapın ki en son sinyal geçerli olsun. ::: ### Özel eylemlerin yapamadıkları \{#what-custom-actions-cant-do\} Özel eylemler statiktir. Action ID, flow'u oluştururken sabitlenir; [değişkenleri](onboarding-variables) veya [kullanıcı girişlerini](builder-inputs-and-forms) okuyamaz. Eylem tetiklendiğinde uygulamanız yalnızca o ID'yi alır; kullanıcının girdiği e-posta, telefon numarası veya başka bir bilgiyi almaz. Giriş alanları, dallanma ve kişiselleştirme için flow içinde değişken olarak kalır. Bu değerleri uygulamanızda kullanmak istiyorsanız kendi arayüzünüz veya API'niz aracılığıyla toplamanız gerekir. Özel eylemler de tek yönlüdür. Uygulamanız flow'a bir sonuç döndüremez ve flow, kodunuzun bitmesini beklemez. Özel eylemin ardından bir **Navigate next** eylemi geliyorsa, kodunuz başarısız olsa bile kullanıcı bir sonraki ekrana geçer — örneğin kullanıcı giriş ekranını oturum açmadan kapattığında. Statik Action ID ile birleşince bu durum, uygulamanızda kullanıcı girişini doğrulamayı olanaksız kılar — örneğin kullanıcının girdiği bir SMS kodunu kontrol edip sonuca göre dallanmak gibi. Flow'un geri kalanı kodunuzun ne yaptığına bağlıysa [flow'u iki placement arasında bölün](#continue-the-flow-based-on-the-result). ### Sonuca göre flow'u devam ettirme \{#continue-the-flow-based-on-the-result\} Bazı ekranların yalnızca özel bir eylem başarıyla tamamlandıktan sonra görünmesi gerekiyorsa — örneğin giriş işleminin ardından gelen ekranlar — flow'u iki [placement](placements) arasında bölün ve uygulamanızın ikinci bölümü ne zaman göstereceğine karar vermesine izin verin: 1. İlk placement'ta, özel bir eylemle biten bir flow oluşturun (örneğin `login`). 2. Uygulamanızda Action ID'yi işleyin: giriş ekranınızı gösterin ve kullanıcının oturum açıp açmadığını kontrol edin. 3. Kullanıcı oturum açtıysa, takip eden ekranlarla birlikte ikinci placement'taki flow'u gösterin. Bu sayede, uygulamanız geçişi flow'un sonuçtan bağımsız olarak ilerlemesi yerine gerçek sonuca göre kontrol eder. ## Koşullu eylemler \{#conditional-actions\} <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/xmWSEPxnI0s?si=mazHQHE89qEDxvPA" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Kullanıcı verilerine göre flow'u farklı yollara ayırmak için koşullu eylemler kullanın. Yaygın kullanım senaryoları şunlardır: - Ekranda bir test var ve kullanıcıları cevaplarına göre farklı ekranlara yönlendirmek istiyorsunuz. Bu durumda bir butona koşullu eylem ekleyin. - Farklı kullanıcı gruplarına farklı ürünler ve teklifler sunmak istiyorsunuz. Bunları farklı ekranlara yerleştirin ve bir gezinme butonu için koşullar ayarlayın. - Önceki bir uygulama oturumunda zaten bir öğreticiyi tamamlamış kullanıcılar için belirli adımları atlamak istiyorsunuz. Koşullu eylemler, bir if / else-if / else zinciri gibi çalışır. Uygulama kuralları yukarıdan aşağıya okur ve ilk eşleşmede durur: 1. **IF**: Flow birincil koşulu kontrol eder. - Doğru mu? Flow, THEN eylemlerini hemen çalıştırır ve durur. - Yanlış mı? Flow bir sonraki bölüme geçer. 2. **ELSE IF**: Buraya ek kontroller ekleyebilirsiniz (örn. "Premium değilse, kullanıcı Deneme sürümünde mi?"). 3. **ELSE** (Yedek): Yukarıdaki kuralların hiçbiri eşleşmediyse, flow bu son bölümdeki eylemleri çalıştırır. :::important - Bir kural eklenmiş ancak herhangi bir eylem atanmamışsa, koşulun eşleşmesi hiçbir şey yapmaz. - Eksik bir kural (operatör veya değer girilmemiş) [önizleme ve yayınlamayı engeller](builder-save-publish#troubleshooting). ::: Her kural için değerlendirilecek bir değişken ve çalıştırılacak bir eylem seçin. Kural başına birden fazla eylem ekleyebilirsiniz. :::important Flow yalnızca bir kuralı çalıştırır — eşleşen ilk kuralı. Hem **IF** hem de **ELSE IF** eylemlerini aynı anda çalıştırmanız gerekiyorsa her iki eylemi de **IF**'e ekleyin. ::: Öğeleri seçilebilir hale getirmeyi ve koşullarda kullanmak üzere gruplara düzenlemeyi öğrenmek için bkz. [Seçilebilir öğeler ve gruplar](flow-selectable-elements). ## Sorun Giderme \{#troubleshooting\} Zorunlu alanlar eksik olduğunda herhangi bir işlem önizlemeyi ve yayımlamayı engeller. Tam liste için [Flow'ları kaydet ve yayımla](builder-save-publish#troubleshooting) bölümüne bakın. --- # File: builder-loaders-and-progress-bars --- --- title: "İlerleme göstergeleri ve yükleyiciler" description: "Flow içinde adım ilerlemesini ve meşgul durumlarını gösterin." --- **Progress** kategorisi iki element türü sunar: çok ekranlı bir flow'da adım tabanlı ilerleme için bir tür ve yerinde meşgul göstergeleri için bir tür. ## İlerleme göstergeleri \{#progress-indicators\} ### Gösterge stilleri \{#indicator-styles\} **Progress** öğesi, kullanıcının çok ekranlı bir flow içindeki konumunu gösterir. Bu kategori üç görsel varyant sunar: - **Linear** — Kullanıcı ilerledikçe dolan tek bir çubuk. - **Segmented** — Her adım için ayrı ayrı dolan çubuklar. - **Connectors** — Çizgilerle birbirine bağlı etiketli daireler (örneğin sırayla Adım 1, Adım 2, Adım 3). ### Adımları ekranlarla eşleştirme \{#match-steps-to-screens\} Varsayılan olarak İlerleme Göstergesi, flow'daki tüm ekranları izler. Bunu belirli bir alt kümeyle sınırlamak için **Screens** açılır menüsünden seçim yapın. Alternatif olarak, dışarıda bırakmak istediğiniz ekranı açıp **Include screen in progress indicator** onay kutusunun işaretini kaldırın. Adım sayısı üzerinde daha ayrıntılı kontrol gerekiyorsa **One segment per screen** geçişini kapatın. :::warning Adım pozisyonu, kullanıcının gerçekte gördüğü sırayı değil, ekran listesini takip eder. Doğrusal olmayan flow'larda göstergenin görüntülenen adımı ileri atlayabilir ya da geri dönebilir. ::: ### Adım durumları \{#step-states\} Her adımın üç durumu vardır — **Completed**, **Current** ve **Upcoming**. Bir durumun stilini sağ panelde düzenlemek için Progress Indicator içindeki bir adımı seçin. Düzenlemelerinizi diğer iki duruma kopyalamak için **Apply changes to all states** seçeneğini kullanın. Bir adımı düzenlemek, aynı göstergedeki tüm adımları etkiler. ### Düzen ve konumlandırma \{#layout-and-positioning\} İlerleme göstergesi global bir öğedir; bu nedenle onu bir [kapsayıcının](builder-containers) içine yerleştiremezsiniz. Konumunu da ayarlayamazsınız — varsayılan olarak mutlak konumlandırma kullanır. Kullanıcı ekranı kaydırdığında gösterge yerinde kalır ve içerik onun altında kayar. Göstergenin etrafındaki boşluğu ayarlamak için öğeyi taşımak yerine **Spacing** bölümündeki **Margin** ve **Padding** kontrollerini kullanın. Düzen bozuk görünüyorsa hem göstergede hem de komşu öğede margin veya padding'i ayarlayın. ## Yükleyiciler \{#loaders\} **Yükleyici**, bir işlemin sürdüğünü bildiren animasyonlu bir öğedir; örneğin kullanıcının quiz yanıtlarının kişiselleştirilmiş bir plan hazırlamak üzere işlenmesi gibi. Kategoride üç şablon bulunur: - **Spinner** — Dönen dairesel bir simge. - **Spinner with label** — Açıklamalı dönen dairesel bir simge (örneğin, "Yükleniyor..."). - **Loader** — İşlem ilerledikçe dolup biten yatay bir çubuk. {/* - **Loader with label** — A horizontal bar with a caption and percentage (e.g., "Analyzing... 47%"). */} :::warning Bir yükleyicinin görünmesi ve kaybolması için bir **tetikleyici** gerekir. Bu mantığı ayarlamak için **Interactions** sekmesini açın — örneğin, kullanıcı bir quiz gönderdikten sonra gösterin. ::: --- # File: onboarding-variables --- --- title: "Değişkenler" description: "Flow'larınızda dinamik veri görüntülemek için değişkenleri kullanın." --- Değişkenler, flow'larınızda dinamik içerik görüntülemenizi sağlar — ürün fiyatlandırması, teklif detayları ve her kullanıcının bağlamına göre güncellenen diğer veriler. Öğe görünürlüğünü kontrol etmek ve ekran içeriğini kişiselleştirmek için kullanın. Değişken panelini açmak için sol paneldeki **{ }** simgesine tıklayın. Panelde üç sekme bulunur: - **[Özel](#custom-variables)**: Kendiniz oluşturup yönettiğiniz değişkenler. - **[Ürün](#product-variables)**: Mağazadan yerelleştirilmiş ürün ve teklif verilerini çeken yerleşik değişkenler. - **[Element](#element-variables)**: Tuvaldeki element durumlarına bağlı değişkenler. ## Özel değişkenler \{#custom-variables\} ### Özel değişken oluşturma \{#create-a-custom-variable\} 1. Değişken panelinde **+** butonuna tıklayın. 2. Değişken için bir ad girin. 3. Tür seçin: String, Number veya Boolean. 4. Başlangıç değeri belirleyin. Bu, flow başladığında değişkenin alacağı değerdir. 5. **Create variable** butonuna tıklayın. :::tip İlgili değişkenleri gruplamak için adlarda nokta kullanabilirsiniz — örneğin `user.score` veya `user.goal`. ::: ### Bir etkileşim aracılığıyla değişken güncelleme \{#update-a-variable-via-an-interaction\} :::link Daha fazla bilgi için [Eylemler](onboarding-actions) makalesine bakın. ::: Herhangi bir elemana **Set up variables** eylemi ekleyerek çalışma zamanında bir değişken değerini güncelleyebilirsiniz. 1. Tuvalde bir eleman seçin. 2. **Interactions** sekmesinde **Add trigger** seçeneğine tıklayın. 3. **On tap** seçeneğini belirleyin ve **Add action** seçeneğine tıklayın. **Action type** açılır menüsünden **Set up variables** seçeneğini belirleyin. 4. **Add variable** seçeneğine tıklayın. Değişkeni seçin ve yeni değeri belirleyin. :::tip Örneğin, bir kullanıcının hangi test sorusu cevabını seçtiğine göre `user.goal` değişkenine farklı bir değer atayabilir, ardından bu değişkeni kullanarak kullanıcıyı farklı bir ekrana yönlendirebilirsiniz. ::: ## Ürün değişkenleri \{#product-variables\} Ürün değişkenleri, yerelleştirilmiş verileri doğrudan uygulama mağazalarından çeker. Yerelleştirilmiş fiyatları, başlıkları ve teklif ayrıntılarını görüntülemek için metin alanlarında, ya da teklif uygunluğuna göre içerik gösterip gizlemek için koşullarda kullanabilirsiniz. | Değişken | Açıklama | Örnek | | :--- | :--- | :--- | | `prod_title` | Ürünün yerelleştirilmiş başlığı | Premium Subscription | | `prod_price` | Bir faturalandırma dönemi için yerelleştirilmiş fiyat | $9.99 | | `prod_price_per_day` | Abonelik fiyatının faturalandırma dönemindeki günlere bölünmüş hali. Abonelik olmayanlar için boş. | $0.33 | | `prod_price_per_week` | Abonelik fiyatının faturalandırma dönemindeki haftalara bölünmüş hali. Abonelik olmayanlar için boş. | $2.33 | | `prod_price_per_month` | Abonelik fiyatının bir aya göre düzenlenmiş hali. Abonelik olmayanlar için boş. | $9.99 | | `prod_price_per_year` | Abonelik fiyatının bir yıla göre düzenlenmiş hali. Abonelik olmayanlar için boş. | $119.88 | | `offer_price` | Başlangıç veya promosyon teklifinin yerelleştirilmiş fiyatı. Kullanıcı herhangi bir teklife uygun değilse boş. | $0.99 | | `offer_billing_period` | Bir teklifin yerelleştirilmiş faturalandırma dönemi. Deneme ve peşin ödeme teklifleri için `offer_full_duration` ile aynıdır. Kullanıcı uygun değilse boş. | 1 week | | `offer_full_duration` | Bir teklifin yerelleştirilmiş toplam süresi. Kullanıcı uygun değilse boş. | 1 month | | `is_free_trial` | Kullanıcı ücretsiz deneme içeren bir teklife uygunsa `true` döndürür. | true | | `is_pay_up_front` | Kullanıcı peşin ödeme teklifine uygunsa `true` döndürür. | true | | `is_pay_as_you_go` | Kullanıcı kullandıkça öde teklifine uygunsa `true` döndürür. | true | :::tip Kullanıcının uygun olduğu teklife göre öğeleri göstermek veya gizlemek için `is_free_trial`, `is_pay_up_front` ve `is_pay_as_you_go`'yu koşullu görünürlükle kullanın. Örneğin, yalnızca `is_free_trial` `true` olduğunda ücretsiz deneme zaman çizelgesini gösterin. ::: Teklif değişkenlerinin değerleri, kullanıcının uygun olduğu teklif türüne göre değişir. Bunu açıklamak için, haftalık $5 fiyatlı "Premium Subscription" adlı bir aboneliği ve üç olası teklifi ele alalım: - **Pay As You Go**: İlk 3 hafta $3 (haftalık faturalandırılır), sonra $5/hafta. - **Pay Up Front**: İlk 3 hafta $8 (hemen faturalandırılır), sonra $5/hafta. - **Free Trial**: İlk hafta ücretsiz, sonra $5/hafta. Bu örnekte, `prod_title` "Premium Subscription" değerini, `prod_price` ise $5 değerini döndürür. Teklif değişkenlerinin değerleri, kullanıcının hangi teklife uygun olduğuna bağlıdır: | Değişken | Pay As You Go | Pay Upfront | Free Trial | | :--- | :--- | :--- | :--- | | `offer_price` | $3 | $8 | $0 | | `offer_billing_period` | 1 hafta | 3 hafta | 1 hafta | | `offer_full_duration` | 3 hafta | 3 hafta | 1 hafta | Peşin Ödeme ve Ücretsiz Deneme teklifleri için `offer_billing_period` ve `offer_full_duration` aynı değeri döndürür. Haftalık Öde teklifinde ise fatura dönemi bir hafta, tam süre üç hafta olduğundan bu iki değer birbirinden farklıdır. :::note Teklifler ve yapılandırma hakkında daha fazla bilgi için [Teklifler](offers) bölümüne bakın. ::: ## Eleman değişkenleri \{#element-variables\} Eleman değişkenleri, kullanıcının yaptığı seçimleri yakalar; testlerde ne seçtiklerini, hangi sekmede olduklarını ve deneme süresi toggle'ının açık olup olmadığını kaydeder. Eleman değişkeni türleri gruba göre değişir: - **Tekli seçim**: Tekli seçim testleri ve sekmeler: - `selected_id`: Koşullarda kullanılacak eleman ID'si - `selected_title`: Dinamik metinde kullanılacak eleman başlığı - **Çoklu seçim**: Çoklu seçim testleri: - `selected_ids`: Koşullarda kullanılacak eleman ID'leri - `selected_titles`: Dinamik metinde kullanılacak eleman başlıkları - **Toggle**: Deneme süresi toggle'ı: - `is_selected`: Boolean değeri Yaygın kullanım senaryoları şunlardır: - Deneme sürümü geçiş düğmesinin etkin olup olmadığına göre farklı içerik gösterme. - Kullanıcıları quiz yanıtlarına göre [farklı ekranlara yönlendirme](onboarding-navigation-branching) ## Metinde değişken kullanma \{#use-variables-in-text\} Bir metin öğesine değişken eklemek için: 1. Canvas üzerinde bir metin öğesi seçin. 2. **Design** sekmesinde **Content** alanını bulun ve metninizi yazın. 3. Alandaki **{ }** simgesine tıklayın. 4. Listeden bir değişken seçin. :::tip Değişkenleri diğer öğelerde de kullanabilirsiniz: - Bağlantıları ve uyarıları dinamik hale getirmek için değişken kullanın - Değişkenlere dayalı dinamik koşullar oluşturun. Örneğin, koşul şu şekilde olabilir: `if experience.current > experience.target, navigate to...` ::: ### Stil değişkenleri \{#style-variables\} Bir değişkene tek başına zengin metin biçimlendirmesi uygulayamazsınız. **Content** alanında bir değişken seçip kalın, italik, altı çizili, üzeri çizili veya renk değişikliği uygulamanın herhangi bir etkisi olmaz. Zengin metin ayarları yalnızca tüm metin bloğuna uygulanır. Metni biçimlendirmek için **Design** sekmesindeki **Typography** bölümünü kullanın ya da kayıtlı bir [metin stili](onboarding-text#set-up-text-styles) uygulayın. ### Ekranlar arasında içerik yeniden kullanımı \{#reuse-content-across-screens\} Flow'unuzda bazı içerikler tekrar eder — "Continue" gibi bir düğme etiketi, tekrarlayan bir eylem çağrısı veya birden fazla ekranda gösterilen bir sorumluluk reddi metni. Aynı durum, birden fazla ekranda yeniden kullanılan özellik açıklamaları gibi daha uzun metinler için de geçerlidir. Bu içerikleri her elemana ayrı ayrı yazmak yerine, özel bir değişkende saklayın. Bu yöntem, farklı kullanıcıları farklı ekranlara yönlendirirken tutarlı bir ifade kullanmak istediğinizde işinizi kolaylaştırır. 1. String türünde bir [özel değişken oluşturun](#create-a-custom-variable) ve başlangıç değerini yeniden kullanmak istediğiniz metne ayarlayın. Örneğin, adını `button.navigation` olarak belirleyip değerini `Continue` yapabilirsiniz. 2. Bu değişkeni, metnin görünmesini istediğiniz her öğenin **Content** alanına ekleyin. Metni her yerde değiştirmek için değişkenin başlangıç değerini bir kez güncelleyin. Değişkeni kullanan her öğe otomatik olarak güncellenir, böylece her ekranı tek tek düzenlemek zorunda kalmazsınız. --- # File: onboarding-element-visibility --- --- title: "Koşullu görünürlük" description: "Öğeleri koşullara göre gösterin veya gizleyin." --- <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/3w3YSOmI3tQ?si=vPhoQGt44SI285Ru" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Bir öğeye koşul ekleyerek görünür olup olmayacağını kontrol edebilirsiniz. Koşullu bir öğe, yalnızca belirtilen kriterleri karşılayan kullanıcılara görünür. :::important Bir öğeyi **Show** veya **Hide** [eylemiyle](onboarding-actions) gösterip gizlediğinizde, bu eylem o öğe üzerinde ayarlanmış **Visibility** koşulunu geçersiz kılar. **Visibility** koşullarını, sabit bir kritere göre her zaman görünür ya da gizli olması gereken öğeler için kullanın. Eylemleri ise görünürlüğün kullanıcı etkileşimine göre değişmesi gerektiğinde kullanın; örneğin bir kullanıcı quiz sorusunu yanıtladıktan sonra bir düğme göstermek için. ::: Bir elemana koşul eklemek için: 1. Tuvalde veya katman panelinde elemana tıklayın. 2. Sağ panelin **Visibility** bölümünde **Conditional** seçeneğini seçin. 3. Üç sekmeden birinden bir özellik türü seçerek koşulu ayarlayın: - **Custom**: Oluşturduğunuz ve yönettiğiniz değişkenler; değerleri kullanıcı etkileşimleri aracılığıyla güncellenebilir. Ayrıntılar için [Değişkenler](onboarding-variables) sayfasına bakın. - **Products**: Flow'unuzdaki ürünlerin fiyat veya ad gibi özellikleri. - **Elements**: Flow'daki diğer öğelerin durumları; örneğin bir deneme süresinin (trial) açık olup olmadığı. 4. Eşleştirilecek **Value** değerini girin. 5. Gerekirse operatöre tıklayarak değiştirin. 6. (İsteğe bağlı) Daha fazla koşul eklemek için **Add condition** seçeneğine tıklayın. Tüm koşulların mu yoksa herhangi birinin mi sağlanması gerektiğini belirtmek için seçiciyi kullanın. --- # File: paywall-dark-mode --- --- title: "Karanlık mod" description: "Kullanıcı deneyimini iyileştirmek için Adapty'deki flow'larda karanlık modu yapılandırın." --- Adapty flow'ları karanlık modu kutudan çıkar çıkmaz destekler. Varsayılan olarak, renk stillerinin hem açık hem de koyu bir alternatifi vardır — bir öğeye renk stili uyguladığınızda, flow cihazın mevcut moduna göre doğru değeri kullanır. Adapty önceden yapılandırılmış bir dizi renk stili sunar ve kendi stillerinizi de oluşturabilirsiniz. ## Renk stillerini yapılandırma \{#configure-color-styles\} Her **renk stili**, bir açık ve bir koyu renk alternatifi tanımlar. Bir öğe adlandırılmış bir stil kullandığında, iki renk arasında otomatik olarak geçiş yapar. Renk stillerini sol paneldeki **Style** > **Colors** bölümünden yönetebilirsiniz. Renk stili eklemek için: 1. **Style** > **Colors** bölümünde **Create style** seçeneğine tıklayın. 2. Açık ve koyu renk alternatiflerini seçin. Bir stili yeniden adlandırmak için yanındaki **⋮** simgesine tıklayın ve **Rename** seçeneğini belirleyin. ## Durum çubuğu temasını ayarlama \{#set-the-status-bar-theme\} **Screen settings** panelinde **Status bar** etkinleştirilmişse temasını bağımsız olarak ayarlayabilirsiniz: **Status bar theme** seçeneklerinden **Light**, **Dark** veya **Auto** seçin. ## Açık ve koyu mod önizlemesi \{#preview-light--dark-modes\} Flow'unuzun her iki modda nasıl göründüğünü önizlemek için önizleme alanının altındaki güneş/ay simgesi geçiş düğmesini kullanın. ## Koyu modu kaldırma \{#remove-dark-mode\} Koyu mod desteğini tamamen kaldırmak için **Style** > **Colors** panelinde **⋮** > **Delete dark theme** seçeneğine tıklayın. --- # File: add-paywall-locale-in-adapty-paywall-builder --- --- title: "Flow Builder'da yerel ayar ekleme" description: "Kullanıcılara kendi dillerinde ulaşmak için Adapty'nin Flow Builder'ında yerelleştirilmiş içerik ekleyin." --- Flow'larınızı yerelleştirmek, bunları birden fazla dilde kullanılabilir hale getirir. Flow Builder'da yerelleştirme ekran bazında düzenlenir; her ekranda çeviri ilerlemenizi takip etmek için bir tamamlanma yüzdesi gösterilir. :::tip Başka diller eklemeden önce flow'unuzu varsayılan yerel ayarda tamamlayın. ::: ## Yerelleştirme ekleme ve ayarlama \{#add-and-set-up-localization\} 1. Sol panelde Localizations simgesine tıklayın. Ardından **Add locale** seçeneğine tıklayın. Eklemek istediğiniz dilleri seçin. 2. Eklenen her yerel ayar, yerelleştirme tablosunda ayrı bir sütun olarak görünür ve varsayılan dil değerleriyle önceden doldurulur. 3. Yalnızca eksik çevirilere odaklanmak için sol paneldeki **Missing only** geçiş düğmesini açın. Tablo, yalnızca çevrilmemiş satırları gösterecek şekilde filtrelenir. ## Harici çeviri için dışa ve içe aktarma \{#export-and-import-for-external-translation\} Çeviri dosyasını çevirmenlerle paylaşmak için dışa aktarabilir, çevrilen sonuçları da içe aktarabilirsiniz. Üst araç çubuğunda **Import / Export** seçeneğine tıklayın. ### Dışa aktarma dosya biçimi \{#export-file-format\} Dışa aktarma işlemi, çevrilebilir her öğe için bir satır içeren `.tsv` (sekmeyle ayrılmış) bir dosya oluşturur. Sütunlar şunlardır: | Sütun | Açıklama | |--------|-------------| | `Screen` | Öğenin ait olduğu ekran (örn. `Welcome`, `Quiz`) | | `Element` | O ekrandaki otomatik oluşturulan öğe tanımlayıcısı. **Interactions** > **Element ID** bölümünden değiştirebilirsiniz. | | `Property` | Özellik türü (örn. `content`) | | `[default_locale]` | Varsayılan dil kodu (örn. `en`) | | `[locale]` | Eklenen her yerel ayar için bir sütun (örn. `fr`, `es`) | Örnek: :::note Çevrilmemiş satırlar için yerel ayar sütunlarını boş bırakın — Adapty bunları eksik olarak değerlendirecektir. ::: ### İçe aktarma dosyası gereksinimleri \{#import-file-requirements\} - **Format**: `.tsv` (sekmeyle ayrılmış değerler) - **Başlıklar**: `Screen`, `Element`, `Property` ve en az bir yerel ayar sütunu içermelidir - **Yerel ayar sütun adları**: flow'a zaten eklenmiş yerel ayar kodlarıyla eşleşmelidir. Flow'da bulunmayan yerel ayar kodları içeren bir dosya içe aktarılırsa hata oluşur. - **Kısmi içe aktarma**: yalnızca belirli satırları ekleyebilirsiniz; dosyada yer almayan satırlar mevcut değerlerini korur ## Manuel olarak çevirin \{#translate-manually\} Ayrıca çevirileri doğrudan yerelleştirme tablosundaki herhangi bir hücreye yazabilirsiniz. Belirli bir satırı yönetmek için bağlam menüsünü açın (**⋮**): - **Reset to default**: Satırın çevirisini varsayılan dil değerlerine geri döndürür. ## Yerelleştirmeyi önizleme \{#preview-the-localization\} Çevirilerinizi kontrol etmek için Flow Builder'da aktif locale'i değiştirin ve her ekranı gözden geçirin. --- # File: add-flow-remote-config-locale --- --- title: "Remote config ile flow'u yerelleştirme" description: "Farklı dil veya bölgelere göre farklı değerler sunmak için bir flow'un remote config'ine locale ekleyin." --- Bir flow'un remote config'i, her locale için ayrı bir JSON verisi tutabilir. Çalışma zamanında SDK, kullanıcının locale'ine uyan veriyi döndürür; böylece yeni bir uygulama sürümü göndermeden çevrilmiş metinler, farklı görseller veya locale'e özgü diğer değerleri sunabilirsiniz. ## Yerel ayar ekleme \{#add-a-locale\} Bir flow'un remote config'ine yerel ayar eklemek için: 1. Flow'u Flow Builder'da açın. 2. Ekran önizlemesinin üzerindeki remote config simgesine tıklayın. 3. Editörün üzerindeki **Add locale** düğmesine tıklayın. 4. İletişim kutusunu doldurun: - **Code**: Yerel ayar kodu, örneğin `en`, `fr` veya `de`. - **Name**: Görünen ad, örneğin English veya French. Adapty, JSON editörüne söz konusu yerel ayar için yeni bir sütun ekler. ## Değerleri lokale göre düzenleme \{#edit-values-per-locale\} Her lokal sütunu kendi JSON formatındaki verilerini kabul eder. Sütunlar arasında aynı anahtarları kullanın ve her lokale için değerleri çevirin. Örneğin, İngilizce sütunu: ```json showLineNumbers { "title": "Try for free!", "cta": "Continue", "trial_days": 7 } ``` Ve İspanyolca sütunu: ```json showLineNumbers { "title": "¡Prueba gratis!", "cta": "Continuar", "trial_days": 7 } ``` Sütunlar birbirinden bağımsızdır; birini düzenlemek diğerlerini etkilemez. ## Uygulamanızda eşleşen locale'i okuma \{#read-the-matching-locale-in-your-app\} SDK, `AdaptyFlow.remoteConfigs` üzerinde her locale için bir `AdaptyRemoteConfig` girdisi sunar. `locale` değeri kullanıcınıza uyan girdiyi seçin, ardından çalışma zamanında değerleri kullanmak için `dictionary` veya `jsonString` alanını okuyun. ## Yerel ayarları yedekleme veya taşıma \{#back-up-or-move-locales\} Uzak yapılandırmanızı yedeklemek veya flow'lar arasında kopyalamak için düzenleyicinin üzerindeki **Import/Export** menüsünü kullanın. Dışa aktarılan JSON dosyası, tüm yerel ayarların içeriğini tek seferde barındırır. Dosya formatı için [Flow'u remote config ile özelleştirme](customize-flow-with-remote-config) bölümüne bakın. --- # File: customize-flow-with-remote-config --- --- title: "Flow'u remote config ile özelleştirin" description: "Flow Builder flow'unuzu remote config JSON yüküyle özelleştirin." --- :::important Bu kılavuz, Flow Builder için remote config'i kapsar. Flow Builder olmadan oluşturulan klasik paywall'lar için bkz. [Paywall'u remote config ile tasarlama](customize-paywall-with-remote-config). ::: Remote Config, SDK'nın çalışma zamanında okuduğu özel bir JSON yükü saklamanıza olanak tanır. Bunu kullanarak yeni bir uygulama sürümü yayınlamadan başlıklar, görseller, fontlar, renkler veya özellik bayrakları gibi değerleri ayarlayabilirsiniz. ## Remote config ile çalışma \{#work-with-remote-config\} Bir flow için remote config'i açmak istiyorsanız, flow editöründeki ekran önizlemesinin üzerindeki Remote Config simgesine tıklayın. **JSON** görünümünde istediğiniz JSON formatındaki verileri girebilirsiniz. Editör, eklediğiniz her yerel ayar için ayrı bir sütun gösterir: :::warning Remote config geçersiz bir JSON içeriyorsa, flow'u ne **kaydedebilir** ne de **yayınlayabilirsiniz**. Önizleme ve yayınlamayı engelleyen sorunların tam listesi için bkz. [Flow'ları kaydet ve yayınla](builder-save-publish#troubleshooting). ::: Bu verilere daha sonra SDK üzerinden `AdaptyFlow` nesnesindeki `remoteConfigs` dizisi aracılığıyla erişebilirsiniz. Adapty, her locale için bir `AdaptyRemoteConfig` girişi saklar; kullanıcınızın locale'iyle eşleşen girişi seçip çözümlenmiş `dictionary`'i veya ham `jsonString`'i okuyarak flow'unuzu çalışma zamanında özelleştirebilirsiniz. Remote config kullanımına ilişkin bazı örnekler aşağıda verilmiştir. <Tabs> <TabItem value="Titles" label="Başlıklar" default> ```json showLineNumbers { "screen_title": "Today only: Subscribe, and get 7 days for free!" } # Test titles or other texts ``` </TabItem> <TabItem value="Images" label="Görseller"> ```json showLineNumbers { "background_image": "https://adapty.io/media/paywalls/bg1.webp" } # Test images on your flow ``` </TabItem> <TabItem value="Fonts" label="Fontlar"> ```json showLineNumbers { "font_family": "San Francisco", "font_size": 16 } # Test fonts ``` </TabItem> <TabItem value="Color" label="Renkler"> ```json showLineNumbers { "subscribe_button_color": "purple" } # Test colors of buttons, texts etc. ``` </TabItem> <TabItem value="HTML" label="HTML"> ```json showLineNumbers { "photo_gallery": "https://adapty.io/media/paywalls/link-to-html-snippet.html" } # Any HTML code that can be displayed in the flow ``` </TabItem> <TabItem value="Soft/Hard Paywall" label="Soft/Hard Paywall"> ```json showLineNumbers { "hard_paywall": true } # By setting it to true, you disallow skipping the paywall without subscribing # You have to handle this logic in your app ``` </TabItem> <TabItem value="Translations" label="Çeviriler"> ```json showLineNumbers { "title": { "en": "Try for free!", "es": "¡Prueba gratis!", "ru": "Попробуй бесплатно!" } } ``` </TabItem> </Tabs> Bu kalıpların herhangi birini birleştirebilir ya da alternatif metin, düzen veya davranışları test etmek için kendi anahtarlarınızı tanımlayabilirsiniz. Sonraki adım olarak [bir placement oluşturun](create-placement) ve flow'u buna ekleyin. Ardından flow'u uygulamanızda render edin: [iOS](present-remote-config-paywalls) veya [Android](present-remote-config-paywalls-android). ## Yerel ayar ekleme \{#add-a-locale\} Flow'unuzu yerelleştirmek için editörün üzerindeki **Add locale** seçeneğine tıklayın ve yerel ayarları seçin. Adapty, o yerel ayar için editöre yeni bir sütun ekler. Her sütunu bağımsız olarak düzenleyin — çalışma zamanında SDK, `locale`'i kullanıcının seçimiyle eşleşen `AdaptyRemoteConfig` girişini döndürür. ## JSON İçe ve Dışa Aktarma \{#import-and-export-json\} Tüm locale'lerdeki remote config'inizi yedeklemek, paylaşmak veya toplu düzenlemek için editörün üzerindeki **Import/Export** menüsünü kullanın. - **Export JSON**: Her locale'i içeren tek bir JSON dosyası indirir. - **Import JSON**: Aynı formatta bir JSON dosyası yükler. Yüklenen dosya mevcut remote config'in yerini alır. Dosya, üst düzey anahtar olarak locale kodlarını, değer olarak ise her locale'in içeriğini kullanır: ```json showLineNumbers { "en": { "title": "Get Premium", "cta": "Continue", "trial_days": 7, "features": ["sync", "export", "ai"] }, "fr": { "title": "Passez à Premium", "cta": "Continuer", "trial_days": 7, "features": ["synchronisation", "exportation", "IA"] } } ``` Her yerel ayar bloğu, doğrudan bir yerel ayar sütununa gireceğiniz JSON yapısının aynısını izler. --- # File: paywall-device-compatibility-preview --- --- title: "Flow'ları önizleme" description: "Optimize edilmiş bir deneyim için farklı cihazlarda flow uyumluluğunu önizleyin." --- Flow'unuzu farklı ekran türlerinde önizlemenin iki yolu vardır: - **Cihazlarda önizleme**: Geliştirmenin herhangi bir aşamasında flow'unuzun gerçek cihazlarda nasıl göründüğünü kontrol edin. - **Adapty Kontrol Paneli'nde önizleme**: Tasarım yaparken flow'unuzu önizleyin. ## Cihazlarda önizleme \{#preview-on-devices\} Flow'unuzu gerçek bir cihazda önizlemek için: 1. [Adapty uygulamasını App Store'dan indirin](https://apps.apple.com/us/app/adapty/id6739359219). 2. Flow builder'da **Test on device** düğmesine tıklayın. 3. Flow dilini seçin. 4. QR kodu cihaz kamerasıyla tarayın veya bağlantıyı açın. Bu, flow'unuzu Adapty mobil uygulamasında açar. :::note Test modunda Adapty, mağazalardaki ürünlerinize erişemez; bu nedenle flow'da görüntülenen fiyatlar gerçek değildir. ::: ### Sorun Giderme \{#troubleshooting\} Aşağıdaki sorunlardan herhangi biri varsa flow'unuzu yayınlayamaz veya önizleyemezsiniz. - Eksik yapılandırmaya sahip bir etkileşim. Sık karşılaşılan durumlar: - Hedef URL'si olmayan bir **Open URL** eylemi. - Hedef belirtilmemiş bir **Navigate to screen** eylemi — eylem ayarlandıktan sonra hedef ekran silindiğinde de ortaya çıkar. - Operatör veya değer içermeyen bir **conditional action**. - Değişken/değer ataması yapılmamış bir **Set Variable** eylemi. - Ürün (uygulama içi mağaza) veya Web Paywall URL'si (web ödemesi) bulunmayan bir **Purchase** eylemi. - Action ID'si olmayan bir **Custom** eylemi. - Başlık veya Mesaj alanı boş olan bir **Show alert** eylemi. - Herhangi bir öğe seçilmemiş **Show** veya **Hide** eylemi. - **Hiç öğe içermeyen bir ekran**. - **Ürün bağlanmamış** bir ürün öğesi — başvurulan ürün kaldırıldığında ortaya çıkabilir. - Geçersiz bir **remote config** JSON'u tüm dağıtım sürecini bozar — taslağı bile kaydedemezsiniz. ## Adapty kontrol panelinde önizleme \{#preview-in-the-adapty-dashboard\} :::tip Flow'unuzun yayınlanmaya hazır olduğundan emin olmak için [gerçek bir cihazda önizleyin](#preview-on-devices) ve hatasız görüntülendiğini doğrulayın. ::: Flow builder'daki önizleme alanını kullanarak flow'unuzu farklı ekran türlerinde önizleyebilirsiniz. Bu, flow'unuzun çeşitli cihaz ve ekran boyutlarında harika göründüğünden emin olmanıza yardımcı olur. Önizlemenin altındaki önizleme kontrollerini kullanarak şunları yapabilirsiniz: - Flow'unuzu önizlemek için cihaz seçebilirsiniz. - Yatay ve dikey önizleme modları arasında geçiş yapabilirsiniz. - Açık ve koyu modlar arasında geçiş yapabilirsiniz. - Diller arasında geçiş yapabilirsiniz. :::tip - Her zaman farklı yerel ayarları önizleyin; çünkü farklı dillerde kelime uzunlukları farklı olabilir ve bu durum ekran düzenini etkileyebilir. - Özel değişkenleri önizlemek için başlangıç değerleri belirleyin. Örneğin, `name` adında bir değişken eklediyseniz, önizleme için başlangıç değerini `Jane Doe` olarak ayarlayabilirsiniz. ::: --- # File: builder-save-publish --- --- title: "Flow'ları kaydet ve yayınla" description: "Flow'ları taslak olarak kaydedin ve kullanıcılara yayınlayın" --- [Flow Builder](adapty-flow-builder), kaydetme işlemini yayınlamadan ayırır. Taslaklar çalışmalarınızı Adapty Kontrol Paneli'nde saklarken, yayınlama mevcut sürümü SDK aracılığıyla kullanıcılara sunar. Bu makale her iki işlemi ve ne zaman kullanılacağını açıklar. ## Flow'u taslak olarak kaydetme \{#save-a-flow-as-a-draft\} :::warning Geçersiz bir [Remote Config](customize-flow-with-remote-config), taslağı kaydetmenizi engeller. ::: Flow Builder, ilerlemenizi dakikada bir otomatik olarak kaydeder. Taslağı manuel olarak kaydetmek için Flow Builder'ın sağ üst köşesindeki **Save draft** düğmesine tıklayın ya da **Cmd/Ctrl + S** tuşlarına basın. Taslaklar yalnızca kontrol panelinde görünür. Flow zaten bir [placement](placements)'a atanmış olsa bile kullanıcıların uygulamada gördüklerini değiştirmez. ## Flow yayınlama \{#publish-a-flow\} Yayınlama işlemi, flow'unuzun mevcut sürümünü SDK aracılığıyla kullanıcılara sunar. Yayınlandıktan sonra yeni sürüm, aynı flow'un daha önce yayınlanmış sürümünün yerini alır. :::note Bir flow'u [placement](placements)'a eklemek için önce yayınlamanız gerekir. Taslak durumundaki bir flow eklenemez. ::: Flow'unuzu yayınlamak için Flow Builder'ın sağ üst köşesindeki **Publish to Live** düğmesine tıklayın. Bundan sonra ne olacağı, flow'un bir placement'a atanıp atanmadığına bağlıdır: - **Flow zaten bir placement'ta**: Kullanıcılar bir sonraki placement isteğinde yeni sürümü görmeye başlar. - **Flow henüz bir placement'ta değil**: Flow'u kullanıcılara göstermeye başlamak için bir [placement](create-placement)'a ekleyin. :::tip Bir flow, her aksiyon, ekran ve ürün öğesi tam olarak yapılandırıldığında yayımlanmaya hazırdır. Yaygın eksiklikler için [Sorun Giderme](#troubleshooting) bölümüne bakın. ::: :::warning [Özel fontlar](using-custom-fonts-in-flow-builder) flow ile birlikte gönderilmez — her font dosyasını uygulama paketinize ayrıca eklemeniz gerekir. Dosya olmadan kullanıcılar sistem varsayılan fontunu görür. Yayınlanmış bir flow'da eski sürümleri bozmadan font değiştirmek için: flow'u kopyalayın, kopyada fontu değiştirin ve kopyayı, o fontu içeren uygulama sürümlerindeki bir [kitleye](add-audience-paywall-ab-test) hedefleyin. ::: ## Flow durumu \{#flow-status\} Her flow, Flows listesinde bir durum gösterir. Bu durum, flow'un kaydetme ve yayımlama yaşam döngüsünde hangi aşamada olduğunu yansıtır. | Durum | Anlam | | :----- | :------ | | **Draft** | Flow hiç yayınlanmadı. Yalnızca bir taslak mevcut, bu yüzden kullanıcılar henüz görmüyor. Bir [placement](placements)'e eklemek için önce taslağı yayınlamanız gerekiyor. | | **Dirty** | Flow yayınlandı, ancak henüz yayınlanmamış kaydedilmiş düzenlemeler var. Siz tekrar yayınlayana kadar kullanıcılar son yayınlanan sürümü görmeye devam eder. | | **Publishing** | Yayınlama işlemi devam ediyor. | | **Failed** | Son yayınlama girişimi başarısız oldu. Varsa, kullanıcılar son yayınlanan sürümü görmeye devam eder. | | **Published** | En son kaydedilen sürüm canlıda. Yayınlanmamış düzenleme yok. | | **Archived** | Flow silindi. | ## Sorun Giderme \{#troubleshooting\} Aşağıdaki sorunlardan herhangi biri varsa flow'unuzu yayınlayamaz veya önizleyemezsiniz. - Eksik yapılandırmaya sahip bir etkileşim. Sık karşılaşılan durumlar: - Hedef URL'si olmayan bir **Open URL** eylemi. - Hedef belirtilmemiş bir **Navigate to screen** eylemi — eylem ayarlandıktan sonra hedef ekran silindiğinde de ortaya çıkar. - Operatör veya değer içermeyen bir **conditional action**. - Değişken/değer ataması yapılmamış bir **Set Variable** eylemi. - Ürün (uygulama içi mağaza) veya Web Paywall URL'si (web ödemesi) bulunmayan bir **Purchase** eylemi. - Action ID'si olmayan bir **Custom** eylemi. - Başlık veya Mesaj alanı boş olan bir **Show alert** eylemi. - Herhangi bir öğe seçilmemiş **Show** veya **Hide** eylemi. - **Hiç öğe içermeyen bir ekran**. - **Ürün bağlanmamış** bir ürün öğesi — başvurulan ürün kaldırıldığında ortaya çıkabilir. - Geçersiz bir **remote config** JSON'u tüm dağıtım sürecini bozar — taslağı bile kaydedemezsiniz. Yayınlamadan önce olası sorunları yakalamak için flow'unuzu [Adapty uygulamasında](paywall-device-compatibility-preview) önizleyin. Flow önizlemede yüklenemezse, daha fazla ayrıntı için hata mesajına bakın. --- # File: flow-metrics --- --- title: "Flow metrikleri" description: "Abonelik gelirini artırmak için flow performans metriklerini takip edin ve analiz edin." --- Adapty, flow'larınızın performansını ölçmenize yardımcı olmak için bir dizi metrik toplar. Paywall metriklerinin aksine, flow metrikleri tamamlanma takibini de içerir; böylece kullanıcıların flow'un hangi ekranında ayrıldığını görebilirsiniz. Görüntülemeler birkaç dakikada bir güncellenirken diğer tüm metrikler gerçek zamanlı olarak güncellenir. Bu belge, mevcut metrikleri, tanımlarını ve nasıl hesaplandıklarını açıklar. :::important Flow geliri, flow gösterildikten sonra gerçekleşen tüm işlemlerden hesaplanır. ::: Flow metrikleri, tüm flow'larınızın performansına genel bir bakış sunmak amacıyla flow listesinde yer alır. Bu birleşik görünüm, her flow için toplanmış metrikleri sunar; böylece etkinliklerini karşılaştırabilir ve iyileştirme alanlarını belirleyebilirsiniz. Her flow'un daha ayrıntılı analizini yapmak için flow detay metriklerine gidin. Burada seçili flow'a özel kapsamlı metrikleri bulacak ve performansı hakkında daha derin bilgi edineceksiniz. ## Metrik kontrolleri \{#metrics-controls\} Sistem, seçilen zaman dilimine göre metrikleri görüntüler ve bunları sol sütun parametresine göre üç girinti düzeyinde düzenler. Yayımlanmış flow'lar için metrikler, flow'un yayımlanma tarihinden bugüne kadar olan dönemi kapsar. Taslak ve arşivlenmiş flow'lar metrik tablosuna dahil edilir; ancak veri yoksa herhangi bir metrik gösterilmeden listelenir. ### Metrik verileri için görünüm seçenekleri \{#view-options-for-metrics-data\} Flow sayfası, metrik verileri için iki görünüm seçeneği sunar: - Placement tabanlı görünüm: Metrikler, flow ile ilişkilendirilen [placement'lara](placements) göre gruplandırılır. Aynı flow'un farklı placement'larda nasıl performans gösterdiğini karşılaştırmak için bu görünümü kullanın. - Kitle tabanlı görünüm: Metrikler, flow'un hedef [kitlesine](audience) göre gruplandırılır. Farklı kitle segmentlerine özgü metrikleri değerlendirmek için bu görünümü kullanın. Flow sayfasının üst kısmındaki açılır menüden tercih ettiğiniz görünümü seçebilirsiniz. ### Kurulum tarihine göre metrikleri filtrele \{#filter-metrics-by-install-date\} **Filter metrics by install date** onay kutusu, işlem veya görüntüleme tarihlerine göre değil, kullanıcıların uygulamanızı yükledikleri tarihe göre veri analizi yapmanızı sağlar. Bu özellik, belirli bir kullanıcı kohortunun kullanıcı edinme performansını ölçmek için oldukça kullanışlıdır. ### Zaman Aralıkları \{#time-ranges\} Metrik verilerini belirli zaman aralıklarına odaklanarak analiz edebilirsiniz; günler, haftalar, aylar veya özel tarih aralıkları seçebilirsiniz. ### Filtreler ve gruplar \{#filters-and-groups\} Adapty, metrik analizini ihtiyaçlarınıza göre özelleştirmek ve filtrelemek için çeşitli araçlar sunar. Metrikler sayfasında farklı zaman aralıklarına, gruplama seçeneklerine ve filtreleme olanaklarına erişebilirsiniz. - Şuna göre filtrele: Attribution (kaynak, reklam grubu, reklam seti, yaratıcı, kampanya), Ülke, Mağaza. - Şuna göre grupla: Flow (varsayılan), Ülke veya Mağaza. Gruplama seçenekleri, yalnızca o boyut için veri mevcut olduğunda açılır listede görünür — örneğin, tüm flow görüntülemeleri tek bir ülkeden geliyorsa Ülke seçeneği sunulmaz. Bu bölümde mevcut kontroller, filtreler, gruplama seçenekleri ve bunların nasıl kullanılacağı hakkında daha fazla bilgiye [bu dokümantasyonda](controls-filters-grouping-compare-proceeds) ulaşabilirsiniz. ### Tek metrik grafiği \{#single-metric-chart\} Grafik bölümü, verilerinizi basit bir çubuk grafikle gösterir. Grafik sayesinde şunları hızlıca görebilirsiniz: - Her metrik için tam sayılar. - Döneme özgü veriler. Grafiğin yanında toplam bir değer gösterilir; bu sayede tüm tabloya tek bakışta ulaşabilirsiniz. Grafiği genişletmek için ok simgesine tıklayın. ### Toplam metrik özeti \{#total-metrics-summary\} Tek metrik grafiğinin yanında bir toplam metrik özeti bölümü bulunur. Bu bölüm, seçilen metriklerin belirli bir zaman noktasındaki kümülatif değerlerini gösterir. Açılır menüyü kullanarak görüntülenen metriği değiştirebilirsiniz. ## Metrik Tanımları \{#metrics-definitions\} ### Görüntüleme & tekil görüntüleme \{#views--unique-views\} **Görüntüleme**, kullanıcıların flow'unuzu kaç kez başlattığını (ilk ekrana ulaştığını) sayar. Birisi iki kez başlatırsa, bu iki görüntüleme ama bir tekil görüntüleme olarak sayılır. Bu metrik, flow'unuzun kaç kez gösterildiğini anlamanıza yardımcı olur. ### Tamamlamalar ve benzersiz tamamlamalar \{#completions--unique-completions\} **Tamamlamalar**, kullanıcıların flow'unuzun son ekranına kaç kez ulaştığını sayar. Bir kullanıcı bunu iki kez tamamlarsa, bu iki tamamlama ama bir benzersiz tamamlama olarak sayılır. ### Benzersiz tamamlanma oranı \{#unique-completions-rate\} Benzersiz tamamlanma sayısının benzersiz görüntülenme sayısına bölünmesiyle elde edilir. Kullanıcıların flow içinde nasıl ilerlediğini anlamak ve nerede ayrıldıklarını tespit etmek için bu metriği kullanın. :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: ### Gelir \{#revenue\} **Revenue**, flow'a atfedilen satın alma ve yenilemelerden elde ettiğiniz toplam USD cinsinden kazancı gösterir. Bu tutar, App Store / Play Store komisyonu dahil herhangi bir kesinti yapılmadan önceki miktardır. ### Gelirler \{#proceeds\} [**Gelirler**](analytics-cohorts#revenue-vs-proceeds), App Store / Play Store komisyonunu kestikten sonra, ancak vergiler öncesinde elde ettiğiniz tutarı gösterir. :::important Uygulamanız indirimli komisyon programına kayıtlıysa Adapty'yi bilgilendirin. Doğru hesaplamalar için [uygulama ayarlarınızda](general) [Small Business Program](app-store-small-business-program) ve [Reduced Service Fee program](google-reduced-service-fee) durumunuzu belirtin. ::: ### Net gelir \{#net-proceeds\} Mağaza komisyonları ve vergiler düşüldükten sonra elde ettiğiniz nihai kazançtır. ### ARPPU ARPPU, ödeme yapan kullanıcı başına ortalama gelirdir. Toplam gelirin benzersiz ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. 15.000 $ gelir / 1.000 ödeme yapan kullanıcı = 15 $ ARPPU. ### ARPU ARPU, flow'u görüntüleyen kullanıcı başına ortalama gelirdir. Toplam gelirin benzersiz görüntüleyici sayısına bölünmesiyle hesaplanır. ### ARPAS ARPAS, aktif abone başına ortalama gelirdir. Toplam gelirin, deneme süresi veya abonelik başlatan abone sayısına bölünmesiyle hesaplanır. Örneğin: 5.000 $ gelir / 1.000 abone = 5 $ ARPAS. ### CR satın almalar ve benzersiz CR satın almalar \{#cr-purchases--unique-cr-purchases\} **Satın almalara dönüşüm oranı**, flow görüntülemelerinin yüzde kaçının satın almayla sonuçlandığını gösterir. Örneğin, 100 görüntülemeden 10 satın alma %10 dönüşüm oranı demektir. **Benzersiz CR satın almalar**, flow'u görüntüleyen benzersiz kullanıcıların yüzde kaçının satın alma yaptığını ölçer; her kullanıcı kaç kez görüntülemiş olursa olsun yalnızca bir kez sayılır. ### CR denemeler ve benzersiz CR denemeler \{#cr-trials--unique-cr-trials\} **Denemelere dönüşüm oranı**, flow görüntülemelerinin yüzde kaçının bir denemeyle sonuçlandığını gösterir. Örneğin, 100 görüntülemeden 10 deneme %10 dönüşüm oranına karşılık gelir. **Benzersiz CR denemeler**, flow'u görüntüleyen benzersiz kullanıcıların yüzde kaçının deneme başlattığını ölçer; her kullanıcı, flow'u kaç kez gördüğünden bağımsız olarak yalnızca bir kez sayılır. ### Satın Almalar \{#purchases\} **Purchases**, yenilemeler dışında flow'unuzdaki tüm işlemleri sayar. Buna şunlar dahildir: - Yeni doğrudan satın almalar. - Flow üzerinde etkinleştirilen deneme sürelerinin ücretli aboneliğe dönüşmesi. - Plan değişiklikleri (yükseltme, düşürme, çapraz geçiş). - Flow üzerindeki abonelik geri yüklemeleri; örneğin otomatik yenileme olmadan süresi dolan bir aboneliğin yeniden etkinleştirilmesi. Bu metrik, flow'unuzdaki yeni işlem aktivitesinin tam bir resmini sunar. ### Denemeler \{#trials\} **Denemeler**, flow'unuz aracılığıyla ücretsiz deneme süresi başlatan kullanıcı sayısını gösterir. Bu metriği, ödeme kararı vermeden önce deneme teklifinizin kullanıcıları ne kadar iyi çektiğini izlemek için kullanın. ### İptal edilen denemeler \{#trials-cancelled\} **Trials cancelled**, deneme süresi boyunca otomatik yenilemeyi kaç kullanıcının kapattığını gösterir. Bu metrik, hizmetinizi denedikten sonra ücretli aboneliğe geçmemeye karar veren kullanıcı sayısını ortaya koyar. ### Geri Ödemeler \{#refunds\} **Geri Ödemeler**, nedeni ne olursa olsun iade edilen satın alma ve aboneliklerin sayısını gösterir. ### İade oranı \{#refund-rate\} **İade oranı**, ilk kez yapılan satın alımlardan iade edilenlerin yüzdesini gösterir. Örnek: 1.000 ilk satın alımdan 5 iade = %0,5 iade oranı. Yenilemeler bu hesaplamaya dahil edilmez. --- # File: fallback-flows --- --- title: "Yedek flow'lar" description: "Cihaz çevrimdışıyken flow'unuzun görünür kalması için Adapty'de yerel yedek flow'lar ayarlayın." --- Akıcı bir kullanıcı deneyimi sağlamak için [flow'larınızın](adapty-flow-builder) **yedek sürümlerini** ayarlamanız önemlidir. Uygulamanız bir flow talep ettiğinde, Adapty SDK'sı yapılandırmasını almak için sunucularımızla iletişime geçer. Cihaz Adapty'e ulaşamazsa (ağ sorunu, sunucu kesintisi), SDK yerel verilere geri döner: - Kullanıcı flow'u daha önce bir kez gördüyse, SDK önbelleğe alınmış kopyayı sunar. - Önbellekte bir şey yoksa, SDK uygulamanın içine yerleştirilmiş yedek yapılandırma dosyasını yükler. Adapty bu yedek dosyaları otomatik olarak oluşturur. Flow yedek paketi, paywall'larla paylaşılır — platform başına tek bir JSON dosyası, her ikisine ait yedek varyasyonları içerir. SDK, ihtiyaç duyduğu bölümü okur. :::important Flow fallback'leri **Adapty SDK 4.0+** paketiyle birlikte gelir. İndirme iletişim kutusunda daha eski bir SDK sürümü seçerseniz, dosya yalnızca paywall ve onboarding varyasyonlarını içerir; flow içermez. Flow fallback'lerine güvenmeden önce uygulamanızın flow destekli bir SDK sürümünde olduğundan emin olun. ::: ## Başlamadan önce \{#before-you-start\} 1. Flow Builder'da bir [flow](adapty-flow-builder) oluşturun. 2. Flow için bir [placement oluşturun](create-placement). ## Yedek dosyayı indirin \{#download-the-fallback-file\} 1. **[Placements](https://app.adapty.io/placements)** sayfasını açın. 2. Sağ üstteki **Fallbacks** düğmesine tıklayın. 3. Açılır menüden hedef platformunuzu seçin. 4. Uygulamanızda kullandığınız SDK sürümüyle eşleşen seçeneği belirleyin. Flow'ları içeren bir paket almak için **Adapty SDK v4.0.0 and higher** (veya daha yeni bir seçenek) seçin. Tarayıcı, platform başına bir JSON dosyası indirir; örneğin `ios_4_0_0_fallback.json`. <details> <summary>Örnek flow yedek girdisi (genişletmek için tıklayın)</summary> ```json "PLACEMENT_ID": { "data": [ { "developer_id": "PLACEMENT_ID", "variation_id": "cb1c0ef8-aecd-4a53-a6f3-b98266e66884", "flow_id": "daf25858-3fa2-4981-8500-9c8a30e5b7e6", "flow_name": "FLOW_NAME", "flow_version_id": "FLOW_VERSION_ID", "placement_audience_version_id": "a9eb3ab8-3178-477d-84d4-ef9d3978e48b", "audience_name": "All Users", "ab_test_name": "", "cross_placement_info": null, "weight": 100, "variations": [ { "variation_id": "cb1c0ef8-aecd-4a53-a6f3-b98266e66884", "paywall_id": "PAYWALL_ID", "paywall_name": "PAYWALL_NAME", "ab_test_name": "", "products": [], "revision": 1, "custom_payload": null, "weight": 100 } ], "remote_configs": [] } ], "meta": { "placement": { "developer_id": "PLACEMENT_ID", "is_tracking_purchases": true, "audience_name": "All Users", "placement_audience_version_id": "a9eb3ab8-3178-477d-84d4-ef9d3978e48b", "revision": 0, "ab_test_name": "" } } } ``` Tam yapı SDK sürümleri arasında değişebilir. Her zaman kendi yazdığınız bir dosya yerine Adapty'nin SDK sürümünüz için oluşturduğu dosyayı kullanın. </details> ## İndirme sonrası \{#after-the-download\} Dosyayı uygulama kodunuza ekleyin, ardından platforma özel kurulum kılavuzunu izleyin. Paywall yedeklerini yükleyen API'lerin aynısı, uygulamanız flow'ları destekleyen bir SDK sürümüne geçtiğinde flow yedeklerini de yükler: - [iOS](ios-use-fallback-paywalls) - [Android](android-use-fallback-paywalls) - [React Native](react-native-use-fallback-paywalls) - [Capacitor](capacitor-use-fallback-paywalls) ## Sınırlamalar \{#limitations\} Yedek flow'lar sabit kodlanmış ve yerel olarak depolanmıştır; bu nedenle canlı flow'ların tam dinamik özelliklerini taşımazlar: - **Placement başına bir varyant.** Bir placement'ta birden fazla flow varsa (farklı kitleler, A/B testi varyantları), yedek dosya en yüksek ağırlığa sahip varyantı ya da en geniş kitleyi kullanır. - **A/B testi yok.** Canlı bir flow A/B testi sunucuda çözümlenir; yedek her zaman tek bir seçilmiş varyantı gösterir. - **Uzaktan güncelleme yok.** Yedeği güncellemek için yeni bir uygulama sürümü yayınlamak gerekir. Remote config aracılığıyla yapacağınız çalışma zamanı güncellemelerini bunun yerine canlı flow üzerinden iletin. - **Yalnızca varsayılan dil.** Yedek, `en` dilini kullanır; yerelleştirilmiş varyantlar pakete dahil edilmez. --- # File: create-product --- --- title: "Ürün oluşturma" description: "Adapty'de gelir yönetimini iyileştirmek için yeni abonelik ürünleri oluşturmaya ilişkin adım adım kılavuz." --- Adapty'de ürün oluşturma yöntemi, bu ürünlerin mağazalarda mevcut olup olmadığına göre değişir: - **[Ürünler App Store ve/veya Google Play'de henüz yoksa, Adapty'de oluşturup doğrudan mağazalara gönderin.](#create-product-and-push-to-store)** - **[Ürünler App Store ve/veya Google Play'de zaten mevcutsa, Adapty'de oluşturup mevcut mağaza ürünleriyle ilişkilendirin.](#create-product-and-connect-existing-store-products)** :::tip Ürünleri [Developer CLI](developer-cli-reference#adapty-products-create) kullanarak programlı olarak da oluşturabilirsiniz. ::: ## Ürünü oluştur ve mağazaya gönder \{#create-product-and-push-to-store\} :::warning Başlamadan önce ihtiyacınız olan mağazalarla entegrasyonu yapılandırdığınızdan emin olun: - [App Store](initial_ios) - [Google Play](initial-android) App Store entegrasyonunu bir süre önce yapılandırdıysanız, [App Store Connect API anahtarını eklediğinizden](app-store-connection-configuration#step-6-add-app-store-connect-api-key) de emin olun. ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/qUpC2XG-r5E?si=7Komyv4_PUQ4FaEH" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Uygulamanıza yeni bir ürün eklemek için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/products)** bölümüne gidin. <img src="/assets/shared/img/products-tab.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Sağ üst köşedeki **Create product** düğmesine tıklayın. Adapty tüm ürün türlerini destekler: abonelikler, consumable olmayan ürünler \(süresiz erişim dahil\) ve consumable ürünler. 3. **Create a new product and push to stores** seçeneğini seçin. <img src="/assets/shared/img/push-to-stores.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Aşağıdaki bilgileri girin: - **Product name**: Adapty kontrol panelinde kullanılacak ürün adını girin. Bu ad esas olarak sizin referansınız için kullanılır, bu yüzden Adapty Kontrol Paneli genelinde en rahat kullanabileceğiniz adı seçebilirsiniz. - **Access Level**: Ürünün ait olduğu [access level](access-level)'ı seçin. Access level, ürün satın alındıktan sonra hangi özelliklerin açılacağını belirlemek için kullanılır. Bu listede yalnızca daha önce oluşturulmuş access level'ların göründüğünü unutmayın. `premium` access level Adapty'de varsayılan olarak oluşturulur, ancak [daha fazla access level ekleyebilirsiniz](access-level). - **Subscription duration**: Listeden abonelik süresini seçin. - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: Abonelik süresi. - **Lifetime**: Uygulamanın premium özelliklerini sonsuza kadar açan ürünler için lifetime süresini kullanın. - **Non-Subscriptions**: Abonelik olmayan ve dolayısıyla süresi bulunmayan ürünler için non-subscriptions'ı kullanın. Bunlar ek özellikler, consumable ürünler vb. için kullanılabilir. - **Consumables**: Consumable ürünler birden fazla kez satın alınabilir. Uygulama kullanım süresi boyunca tüketilebilirler. Oyun içi para birimi ve ekstralar buna örnek gösterilebilir. Consumable ürünlerin access level'ları etkilemediğini unutmayın. Tek seferlik satın alma ile access level tanımlamak için **Non-Subscriptions** kullanın. - **Price (USD)**: Ürünün USD cinsinden fiyatı. Bu fiyat, tüm ülkelerdeki fiyatların otomatik olarak hesaplanıp ayarlanmasında temel olarak kullanılır. Daha sonra [farklı ülke ve bölgeler için fiyatı özelleştirebilirsiniz](edit-product#set-country-specific-prices). <img src="/assets/shared/img/create-product-push.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Save & Continue** düğmesine tıklayın. 6. App Store'da yayınlamayı planlıyorsanız ürün bilgilerini yapılandırın: - **Product ID**: Ürün için kalıcı ve benzersiz bir kimlik oluşturun. - **Product group**: App Store Connect'te oluşturduğunuz mevcut bir ürün grubunu seçin ya da **Create new Product Group** seçeneğine tıklayarak gruba bir ad verin. Adapty grubu oluşturduktan sonra açılır listeden seçebilirsiniz. - **Screenshot**: Sunulan öğe veya hizmeti açıkça gösteren uygulama içi satın alma ekran görüntüsü yükleyin. Bu ekran görüntüsü yalnızca App Store incelemesi için kullanılır ve App Store'da görüntülenmez. Ekran görüntüsü boyutu ve format gereksinimleri için [buraya](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications/) bakın. <img src="/assets/shared/img/push-app-store.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Push data to App Store** düğmesine tıklayın. :::warning Bu uygulama için ilk ürününüzse, App Store Connect'te manuel olarak incelemeye göndermeniz gerekir. Sonrasında bu adım gerekmeyecektir. İnceleme tamamlandığında Adapty'deki ürün durumu otomatik olarak güncellenecektir. ::: 8. Google Play'de yayınlamayı planlıyorsanız ürün bilgilerini yapılandırın: - **Base Product ID**: Ürün için kalıcı ve benzersiz bir kimlik oluşturun. - **Subscription**: Google Play Console'da oluşturduğunuz mevcut bir abonelik grubunu seçin ya da **Create new Product Group** seçeneğine tıklayarak gruba bir ad ve kimlik verin. Adapty grubu oluşturduktan sonra açılır listeden seçebilirsiniz. :::note Ek süre ve Hesap Bekletme Süresi, Play Store kurallarına göre otomatik olarak varsayılan değerlere ayarlanacaktır. Bunları daha sonra Google Play Console'da değiştirebilirsiniz. ::: <img src="/assets/shared/img/push-google-play.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. **Push data to Play Store** düğmesine tıklayın. 10. iOS için, başlangıç teklifini – ücretsiz deneme – yapılandırmak üzere açılır listeden **Free duration** seçeneğini belirleyin. Bu ilk kurulumda bir ücretsiz deneme başlangıç teklifi ekleyebilirsiniz. Ana ürün mağazalar tarafından onaylandıktan sonra, mağaza konsolunuzdaki mevcut ID'leri bağlayarak [daha fazla teklif](offers) ekleyebilirsiniz (ör. promosyon teklifi, geri kazanma teklifi). <img src="/assets/shared/img/intro.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Başlangıç teklifleri Google Play ile otomatik olarak senkronize edilmez. App Store'dan farklı olarak, Google Play'de ayrı bir "başlangıç teklifi" türü yoktur — ücretsiz denemeler ve indirimli tekliflerin tümü, temel planda **teklifler** olarak yapılandırılır. [Teklifi Google Play Console'da oluşturun ve Adapty ürününüze bağlayın](google-play-offers). ::: 11. Son olarak, ürün oluşturma işlemini onaylamak için **Save** seçeneğine tıklayın. ## Ürünü oluştur ve mevcut mağaza ürünleriyle bağlantı kur \{#create-product-and-connect-existing-store-products\} :::warning Başlamadan önce şunları yaptığınızdan emin olun: - İhtiyacınız olan mağazalarla entegrasyonu yapılandırın: - [App Store](initial_ios) - [Google Play](initial-android) - İhtiyacınız olan mağazalarda ürün oluşturun: - [App Store](app-store-products) - [Google Play](android-products) **Oluşturulmuş hiç ürününüz yoksa**, [Mağazalara gönder](#create-product-and-push-to-store) kılavuzunu takip ederek hem Adapty'de hem de mağazalarda aynı anda oluşturmayı düşünebilirsiniz. ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/nlkdKCF0SwY?si=VVigzHcpv3waKJmI" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> Uygulamanıza yeni bir ürün eklemek için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/products)** bölümüne gidin. <img src="/assets/shared/img/products-tab.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Sağ üst köşedeki **Create product** düğmesine tıklayın. Adapty tüm ürün türlerini destekler: abonelikler, consumable olmayan ürünler \(süresiz erişim dahil\) ve consumable ürünler. 3. **Connect an existing store product** seçeneğini seçin. <img src="/assets/shared/img/existing-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Aşağıdaki bilgileri girin: - **Product name**: Adapty kontrol panelinde kullanılacak ürün adını girin. Bu ad yalnızca kendi referansınız içindir; Adapty Kontrol Paneli genelinde kullanmak için en uygun bulduğunuz adı seçebilirsiniz. - **Access Level ID**: Ürünün ait olduğu [access level](access-level)'ı seçin. Access level, ürün satın alındıktan sonra hangi özelliklerin açılacağını belirlemek için kullanılır. Bu listede yalnızca önceden oluşturulmuş access level'lar yer alır. `premium` access level Adapty'de varsayılan olarak oluşturulur, ancak [daha fazla access level ekleyebilirsiniz](access-level). - **Abonelik süresi**: Listeden abonelik süresini seçin. - **Haftalık/Aylık/2 Ay/3 Ay/6 Ay/Yıllık**: Abonelik süresi. - **Lifetime**: Uygulamanın premium özelliklerini sonsuza kadar açan ürünler için lifetime süreyi kullanın. - **Non-Subscriptions**: Abonelik olmayan ve dolayısıyla süresi bulunmayan ürünler için non-subscription kullanın. Bunlar ek özellikler, consumable ürünler vb. için kullanılabilir. - **Consumables**: Consumable öğeler birden fazla kez satın alınabilir. Uygulama kullanım ömrü boyunca tüketilebilirler. Oyun içi para birimi ve ekstralar buna örnek gösterilebilir. Consumable ürünlerin access level'ları etkilemediğini unutmayın. Tek seferlik satın alımdan access level vermek için bunun yerine **Non-Subscriptions** kullanın. - **Fiyat (USD)**: Ürünün USD cinsinden fiyatı. Ürününüz zaten mağazadaysa bu değer gerçek mağaza fiyatını etkilemez; listeden herhangi bir değer seçebilirsiniz. Daha sonra Adapty kontrol panelinden [farklı bölgeler için fiyatları özelleştirebilirsiniz](edit-product#set-country-specific-prices). <img src="/assets/shared/img/product-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Continue** düğmesine tıklayın. 6. Her mağaza için ürün bilgilerini yapılandırın: - **App Store:** - **App Store Product ID:** Ürününüze cihazlarda erişmek için kullanılan bu benzersiz kimliği listeden seçin. Listede göremiyorsanız App Store Connect'teki yapılandırmasını kontrol edin ve bu uygulamaya ait olduğundan emin olun. - **Play Store:** - **Google Play Product ID:** Play Store'daki ürün kimliğidir. Listeden seçin. Listede göremiyorsanız Google Play Console'daki yapılandırmasını kontrol edin ve bu uygulamaya ait olduğundan emin olun. - **Base Plan ID:** Play Store'daki ürün için temel planı tanımlamak amacıyla kullanılan bu kimlik, Play Store'da aboneliğin Ürün Kimliğini eklerken zorunludur. Temel plan; faturalandırma dönemini, yenileme türünü (otomatik yenileme veya ön ödemeli) ve ilgili fiyatı kapsar. Adapty'de aynı aboneliğin farklı temel planlarla her bir kombinasyonu ayrı bir ürün olarak ele alınır. - **Legacy fallback product**: Yedek ürün, yalnızca Adapty SDK'nın eski sürümlerini (2.5 ve altı) kullanan uygulamalar için kullanılır. Google Play Console'da bir ürünü geriye dönük uyumlu olarak işaretleyerek Adapty, bu ürünün eski SDK sürümleri tarafından satın alınıp alınamayacağını belirleyebilir. Bu alan için değeri `<subscription_id>:<base_plan_id>` biçiminde girin. - **Stripe**: - **Stripe Product ID**: Stripe'taki bir ürünün benzersiz tanımlayıcısıdır. - **Stripe Price ID**: Stripe'ta fiyat nesneleri; fiyat tutarının yanı sıra vergi davranışını, hacim kademelerini ve abonelik aralıklarını da kapsar. Tek bir ürünün birden fazla fiyatı olabileceğinden, Adapty'de ürün oluştururken doğru fiyat kimliğini belirtin. - **Paddle**: - **Paddle Product ID**: Paddle'daki bir ürünün benzersiz tanımlayıcısıdır. - **Paddle Price ID**: Paddle'da fiyat nesneleri; fiyat tutarının yanı sıra vergi davranışını, hacim kademelerini ve abonelik aralıklarını da kapsar. Tek bir ürünün birden fazla fiyatı olabileceğinden, Adapty'de ürün oluştururken doğru fiyat kimliğini belirtin. 7. **İsteğe bağlı:** **Add custom store** butonuna tıklayarak herhangi bir özel mağazadan ürün ekleyebilirsiniz. **Manage custom store info** penceresinde mevcut bir özel mağaza seçebilir ya da yeni bir tane ekleyip bununla bir ürün ilişkilendirebilirsiniz. Adapty'nin yalnızca App Store, Google Play ve Stripe üzerindeki işlemleri takip ettiğini unutmayın. Özel mağazalar için işlemleri Adapty sunucu tarafı API'sindeki Set transaction yöntemiyle göndermeniz gerekir. 8. Ürün oluşturmayı tamamlamak için **Save product** butonuna tıklayın. Ürün durumu senkronizasyonu beş dakikaya kadar sürebileceğinden, tabloda güncellenene kadar bekleyin. 9. Gerekirse ürün için [teklif oluşturabilirsiniz](create-offer). Teklif eklemek için **Yes, add offers** seçeneğine tıklayın. Aksi takdirde **No, thanks** seçeneğine tıklayın. :::note Başlangıç teklifleri Adapty'de yalnızca bir ürün mağazaya gönderilirken oluşturulur. İçe aktarma sırasında veya daha önce oluşturulmuş ürünler için başlangıç teklifleri senkronize edilmez ve Adapty'de görüntülenmez; ancak uygulamada düzgün şekilde çalışmaya devam eder. ::: ## Sonraki adımlar \{#next-steps\} Tebrikler! Ürünlerinizi Adapty'ye eklediniz. Peki şimdi ne yapacaksınız? - Henüz başlangıç/promosyon tekliflerini yapılandırmadıysanız, şimdi [yapabilirsiniz](offers). - Bunu yapmak istemiyorsanız ya da zaten yaptıysanız, uygulama içi satın almaları etkinleştirmek için [paywall kurulumuna](quickstart-paywalls) geçin. - Mağaza ürünlerinde değişiklik yapmak istiyorsanız (örneğin bölgesel fiyatlandırma ayarlamak veya ek süreyi yapılandırmak), bunu App Store Connect veya Google Play Console üzerinden yapın. - [Ürünleri daha sonra nasıl düzenleyebileceğinizi](edit-product) okuyun. --- # File: edit-product --- --- title: "Ürünü düzenle" description: "Daha iyi gelir takibi için Adapty'deki abonelik ürünlerinizi düzenleyin ve yönetin." --- Adapty'de ürününüzün adını, access level'ını, bölgesel fiyatlandırmasını ve bağlı mağaza kimliklerini düzenleyebilir; fiyatlandırma değişikliklerini takip etmek için denetim günlüğünü görüntüleyebilirsiniz. Abonelik süresi, ürünü oluşturduktan sonra düzenlenemez; bu nedenle değiştirmek için yeni bir ürün oluşturmanız gerekir. :::warning Herhangi bir ürünü düzenleyebilirsiniz; ancak yayındaki paywallarda kullanılan ürünlerde yapılan değişikliklerin analizlerinizde tutarsızlıklara yol açmadığından emin olmanız kritik önem taşır. **Access level, App Store Ürün Kimliği ve Play Store Ürün Kimliği düzenlenmesi önerilmez**; bu değişiklikler analiz netliğini olumsuz etkileyebilir. Yalnızca ürün kimliğinde yazım hatası gibi bir hata yaptıysanız düzenleyin. Ürünü artık kullanmıyorsanız ve başka bir ürünle değiştirmek istiyorsanız, yeni bir ürün oluşturmanızı ve Paywalls ile A/B testlerini buna göre güncellemenizi şiddetle tavsiye ederiz. ::: ## Ürünü düzenle \{#edit-product\} Ürünü düzenlemek için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/products)** bölümüne gidin. 2. Tablodaki ürün satırına tıklayın ya da ürünün yanındaki üç noktaya tıklayıp **Edit**'i seçin. 3. Açılan **Edit** penceresinde gerekli değişiklikleri yapın. Bu penceredeki seçenekler hakkında daha fazla bilgi için [Ürün oluşturma](create-product) bölümünü okuyun. 4. **Save**'e tıklayın. :::warning App Store Connect veya Google Play Console'da yaptığınız değişiklikler Adapty'ye yansımaz. Adapty'de gösterilen fiyat, ürünü oluştururken belirlenir ve mağazada fiyatı değiştirseniz bile güncellenmez. Bu durum gelir analizlerinizi etkilemez; Adapty gelir verilerini doğrudan mağazalardan çeker. Kontrol panelindeki fiyat alanı yalnızca bilgilendirme amaçlıdır. ::: :::note Access level'ı değiştirirseniz, bu değişiklik yalnızca yeni abonelikler için geçerli olur. Mevcut aboneler için access level değişmez ve bir sonraki abonelik yenilemesinde otomatik olarak güncellenir. ::: <img src={require('./img/edit-product.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Ülkeye özgü fiyatlar belirleyin \{#set-country-specific-prices\} Adapty kontrol panelinden farklı bölgeler için farklı fiyatlar belirleyebilirsiniz; bu ülkeye özgü fiyatlar App Store Connect ve/veya Google Play Console'daki ürünlerinize otomatik olarak uygulanır. Ülkeye özgü fiyatlar belirlemek için: 1. [Ürünü düzenleme için açın](#edit-product). 2. Mağazalardan dışa aktarılan mevcut fiyatlarınızı doğru formatta almak için **Download**'a tıklayın ya da yeni bir CSV dosyası oluşturun. <img src={require('./img/download-prices.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. CSV dosyasındaki fiyatları güncelleyin. [Formata](#csv-file-format) uyun. Herhangi bir ülkenin fiyatını değiştirmeden bırakırsanız veya dosyaya hiç eklemezseniz hiçbir şey olmaz. CSV'yi yüklediğinizde Adapty fiyatları karşılaştırır ve yalnızca farklı olanları günceller. 4. **Edit** penceresinde **Upload**'a tıklayın ve CSV dosyasını seçin. <img src={require('./img/upload-prices.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Değişikliklerin mevcut aboneler için de geçerli olmasını istiyorsanız **Apply to existing subscribers**'ı seçin. 6. Uygulanacak değişiklikleri inceleyin ve **Save changes**'e tıklayın. <img src={require('./img/country-level-price.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### CSV dosya formatı \{#csv-file-format\} :::tip Bir uygulamada benzer ürünleriniz varsa veya farklı uygulamalarda aynı fiyatları belirlemek istiyorsanız aynı CSV dosyasını yeniden kullanabilirsiniz. ::: CSV'deki fiyatları düzenlemenin en kolay yolu [mevcut fiyatlarla bir dosya indirip doğrudan üzerinde düzenlemektir](#set-country-specific-prices). Ancak kendiniz yapıyorsanız dosyanız şu sütunları içermelidir: - `region_name` - `region_code` - `app_store_currency` - `app_store_requested_price` - `play_store_currency` - `play_store_requested_price` Örnek: ``` region_name,region_code,app_store_currency,app_store_requested_price,play_store_currency,play_store_requested_price United States,US,,8.99,,8.99 United Arab Emirates,AE,USD,8.99,AED,39.99 Germany,DE,USD,8.99,USD,8.99 ``` ## Denetim günlüğünü görüntüleyin \{#view-audit-log\} Adapty, her ürün için tüm fiyat değişikliklerini kaydeder; böylece kimin ne zaman değişiklik yaptığını takip edebilirsiniz. Denetim günlüğünü görüntülemek için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/products)** bölümüne gidin. 2. Ürünün yanındaki üç noktaya tıklayın ve **Audit log**'u seçin. Denetim günlüğü tablosu, her fiyat değişikliğini tarih, ekip üyesinin adı ve rolü ile değişiklik sayısıyla birlikte gösterir. Bir olayın ayrıntılı CSV dökümünü indirmek için o satırdaki indirme simgesine tıklayın. <img src={require('./img/audit-log.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: delete-product --- --- title: "Ürünü sil" description: "Adapty'de bir abonelik ürününü uygulamanızın gelir akışını kesintiye uğratmadan nasıl sileceğinizi öğrenin." --- Yalnızca paywallarda kullanılmayan ürünleri silebilirsiniz. Ürünü silmek için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/products)** bölümüne gidin. 2. Ürünün yanındaki **3 nokta** butonuna tıklayın ve **Delete** seçeneğini seçin. <img src="/assets/shared/img/delete-product.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Silmek istediğiniz ürünün adını girin. <img src="/assets/shared/img/b945add-delete_product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Delete forever** butonuna tıklayın. --- # File: add-product-to-paywall --- --- title: "Paywalla ürün ekleme" description: "Adapty'de paywall'lara ürün eklemeyi ve yönetmeyi öğrenin." --- Bir [paywall](paywalls) üzerinde ürünlerin görünür ve seçilebilir olması için şu adımları izleyin: 1. [Paywall oluştururken](create-paywall) **Products** başlığının altındaki **Add product** düğmesine tıklayın. 2. Açılan açılır listeden müşterilerinize gösterilecek ürünleri seçin. Listede yalnızca önceden oluşturulmuş ürünler yer alır. Ürünlerin sırası SDK tarafında korunur; bu nedenle paywall'ı yapılandırırken istediğiniz sırayı göz önünde bulundurmanız önemlidir. Ayrıca isterseniz bir ürün için teklif de belirtebilirsiniz. <img src="/assets/shared/img/0479b51-ad_product_to_paywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Paywall'ın durumuna göre **Create as draft** veya **Save and publish** düğmesine tıklayın. Oluşturulduktan sonra paywall'daki ürünleri düzenlemeniz, eklemeniz veya silmeniz önerilmez; bu işlemler paywall metriklerini olumsuz etkileyebilir. --- # File: virtual-currencies --- --- title: "Sanal para birimleri" description: "Adapty'de uygulama içi para birimlerini tanımlayın, ürünlere bağlayarak kredileri otomatik olarak verin ve her kullanıcı için bakiye takibi yapın." --- <CustomDocCardList ids={['virtual-currency-quickstart', 'create-virtual-currency', 'virtual-currency-balance']} /> Kullanıcılarınıza ürün satın aldıklarında veya aboneliklerini yenilediklerinde sanal para birimi (AI token, kredi veya coin) verin. Bir para birimini bir kez tanımlayın, ödül vermesi gereken ürünlerle ilişkilendirin; Adapty her kullanıcının bakiyesini otomatik olarak günceller ve takip eder. Uygulamanız bu bakiyeyi [sunucu taraflı API](getting-started-with-server-side-api) aracılığıyla okur ve harcar — örneğin her üretim işlemi için token düşmek amacıyla. ## Nasıl çalışır \{#how-it-works\} 1. [Sanal para birimi oluşturun](create-virtual-currency): **Products** bölümünü açın ve **Virtual currency** sekmesine tıklayın. **New virtual currency** butonuna tıklayın. Bir kod, ad ve isteğe bağlı açıklama ile para birimini tanımlayın. 2. **Para birimini ürünlerle ilişkilendirin**: Para birimini tek seferlik veya abonelik ürünleriyle eşleştirin ve her satın alımın kaç kredi kazandıracağını ayarlayın. 3. **Krediler otomatik olarak tanımlanır**: Bir kullanıcı bağlı bir tek seferlik ürün satın aldığında veya bağlı bir aboneliği yenilediğinde, Adapty yapılandırılan kredileri bakiyelerine ekler. 4. **Bakiyeyi okuyun ve harcayın**: Uygulamanız her kullanıcının bakiyesini okur ve sunucu tarafı API'si aracılığıyla kredi verir ya da harcar. 5. **Her değişikliği takip edin**: Her bakiye değişikliği [kullanıcının profilinde](virtual-currency-balance) listelenir. Para kurulumundan API aracılığıyla kredi harcamaya kadar eksiksiz bir adım adım kılavuz için [Sanal para birimi hızlı başlangıç](virtual-currency-quickstart) rehberine bakın. ## Kullanım senaryoları \{#use-cases\} | Uygulama türü | Sanal para birimlerini nasıl kullanabilirsiniz | |---------------|------------------------------------------------| | **Yapay zeka uygulamaları** (görsel, video veya metin üretimi) | Her üretim için kredi tahsil edin. Aboneliğe aylık kredi hakkı ekleyin ve kredi paketlerini tek seferlik ürün olarak satın. | | **Kısa drama ve video uygulamaları** | Bölümleri açmak için coin tahsil edin. Abonelere yinelenen coin hakkı tanıyın ve coin paketlerini tek seferlik ürün olarak satın. | | **Dil öğrenme ve eğitim** | Ücretsiz kullanıcılara sunucu tarafı API aracılığıyla sınırlı sayıda kalp veya can hakkı verin. Ücretli planda daha fazla hak tanıyın veya bakiye kontrolünü tamamen atlayın. | | **Mobil oyunlar** | Yumuşak ve sert para birimini bir arada kullanın: sunucu tarafı API aracılığıyla oynanış karşılığında altın verin, gem'leri para karşılığı satın ve ikisi arasında tek atomik işlemle dönüşüm yapın. | | **Üretkenlik uygulamaları** | OCR veya dışa aktarma gibi maliyetli işlemleri kredilerle ölçün. Ücretsiz kullanıcılara az miktarda hak verin, abonelikle daha fazlasını tanıyın ve toplu işler için kredi paketi satın. | :::tip Abonelik ödenekleri için [kredi son kullanma](create-virtual-currency#link-products) özelliğini etkinleştirin. Kullanılmayan krediler her yenilemede sıfırlandığında, ödenek aboneliği sürdürmek için bir neden olmaya devam eder; yoğun kullanıcılar ise birikmiş stoku harcamak yerine kredi paketi satın alır. ::: ## Sınırlamalar \{#limitations\} - **Cihazlar arası erişim için kimlik doğrulama gereklidir**: Bir bakiye tek bir profile aittir. Anonim bir kullanıcı bakiyesini yalnızca kazandığı cihazda tutar; bu nedenle bakiyenin her cihazda erişilebilir olması için kullanıcıları tanımlayın. Bkz. [Bakiyeler, profiller ve cihazlar](virtual-currency-balance#balances-profiles-and-devices). - **Yalnızca sunucu tarafı**: Henüz bir bakiye okuma veya harcama SDK yöntemi bulunmamaktadır; bu nedenle uygulamanızın bir backend'e ihtiyacı vardır. Backend, bakiyeleri okur ve sunucu tarafı API aracılığıyla kredi ekler ya da harcar. - **Uygulama başına en fazla 20 para birimi**: Tek bir uygulamada en fazla 20 sanal para birimi oluşturabilirsiniz. --- # File: virtual-currency-quickstart --- --- title: "Sanal para birimi hızlı başlangıç" description: "Bir token para birimini uçtan uca ayarlayın: token para birimi oluşturun, abonelikle token verin ve sunucu tarafı API aracılığıyla harcayın." --- :::link Ana makale: [Sanal para birimleri](virtual-currencies) ::: Bu hızlı başlangıç kılavuzu, bir token para birimini uçtan uca kurar: bir abonelik kullanıcılara ayda 1000 token verir ve uygulamanızdaki ücretli işlemler token harcar. Adapty her bakiyeyi takip eder, bu sayede backend'iniz yalnızca bunları okur ve harcar. 1. `TOKENS` para birimi oluşturmak için [Sanal para birimi oluşturma](create-virtual-currency) kılavuzunu izleyin. Bunu Pro aboneliğinize bağlayın ve **Credit per cycle** değerini 1000 olarak ayarlayın. Ekstra token satmak için tek seferlik token paketi ürünlerini de bağlayın. 2. Oluşturma işlemi başlatılmadan önce kullanıcının bakiyesini okumak için [Sanal para birimi bakiyelerini listele](api-adapty/operations/listVirtualCurrencyBalances) çağrısını yapın: ```bash title="Read balances" curl https://api.adapty.io/api/v2/server-side-api/vc/balances/ \ -H "Authorization: Api-Key {your secret key}" \ -H "adapty-customer-user-id: user-42" ``` Yanıt, kullanıcının sahip olduğu her para birimini listeler; örneğin 1000 `TOKENS`: ```json title="Response" { "data": [ { "code": "TOKENS", "name": "Tokens", "balance": 1000, "held": 0, "available": 1000 } ] } ``` 3. Kullanıcı bir üretim işlemi başlattığında, [Sanal para birimi işlemi oluştur](api-adapty/operations/createVirtualCurrencyTransaction) çağrısını negatif bir `amount` değeriyle yaparak token'ları harcayın. Bu örnekte, bir görsel üretimi 100 token'a mal olmaktadır: ```bash title="Spend tokens" curl -X POST https://api.adapty.io/api/v2/server-side-api/vc/transactions/ \ -H "Authorization: Api-Key {your secret key}" \ -H "adapty-customer-user-id: user-42" \ -H "Content-Type: application/json" \ -d '{"items": [{"currency_code": "TOKENS", "amount": -100}]}' ``` Bir işlem atomik yapıdadır ve güncellenmiş bakiyeyi döndürür. Kullanıcı maliyeti karşılayamazsa istek `insufficient_balance` döndürür ve hiçbir şey değişmez. İstekleri güvenli şekilde yeniden denemek için `Idempotency-Key` başlığını ekleyin. 4. Geri kazanma promosyonu çalıştırmak için aynı endpoint'e pozitif bir `amount` ile token'lar verin. Bu şekilde verdiğiniz kredilerin son kullanma tarihi yoktur. 5. Ekonomiyi istediğiniz zaman denetleyebilmek için kullanıcının [profilindeki](virtual-currency-balance) veya [işlem geçmişindeki](api-adapty/operations/listVirtualCurrencyTransactions) her değişikliği inceleyin. --- # File: create-virtual-currency --- --- title: "Sanal para birimi oluştur" description: "Adapty'de bir sanal para birimi oluşturun, ürünlerle ilişkilendirerek satın almaların kredi kazandırmasını sağlayın ve bu kredilerin süresinin dolup dolmayacağını belirleyin." --- :::link Ana makale: [Sanal para birimleri](virtual-currencies) ::: Sanal para birimi kredisi satmak için önce bir sanal para birimi tanımlayın, ardından ürünlerinizle ilişkilendirin. Bu işlemi iki adımda gerçekleştirirsiniz — her ikisi de bu makalede anlatılmaktadır. Bir ürünü bağladığınızda, her satın alma veya yenileme otomatik olarak kredi kazandırır. ## Sanal para birimi oluşturma \{#create-a-virtual-currency\} Adapty Kontrol Paneli'nde **Products** > [**Virtual currency**](https://app.adapty.io/virtual-currency) bölümünü açın. Sanal para birimi oluşturmak için: 1. **New virtual currency** düğmesine tıklayın. Sağ tarafta bir panel açılır ve **General** adımı görüntülenir. 2. Para birimi ayrıntılarını doldurun: - **Code**: Uygulamanızdaki para birimi için `COINS` gibi benzersiz ve **kalıcı** bir tanımlayıcı. Para birimini sunucu tarafı API'sinde tanımlar ve her kullanıcının bakiyesini takip eder. Latin harfleri, rakamları ve alt çizgileri kullanın; en fazla 32 karakter. Küçük harfler otomatik olarak büyük harfe dönüştürülür. - **Name**: `Gold` gibi bir görünen ad. Bunu daha sonra değiştirebilirsiniz. - **Description**: Para birimi hakkında isteğe bağlı bir not. 3. **Link Products** adımına geçmek için **Continue**'ye tıklayın. :::important Para birimini oluşturduktan sonra **Code** alanını değiştiremezsiniz. **Name** alanını ise sonradan düzenleyebilirsiniz. ::: Yeni bir para birimi eklediğinizde, her kullanıcı profilinin başlangıç bakiyesi 0 olur. ## Ürünleri bağla \{#link-products\} Bir satın alma veya yenilemenin o para birimiyle kredi kazandırması için bir ürünü sanal para birimiyle ilişkilendirin. Bir ürünü birden fazla para birimiyle, bir para birimini de birden fazla ürünle ilişkilendirebilirsiniz. Ürünleri şimdi, **Link Products** adımında bağlayabilir ya da daha sonra para birimini düzenlerken ekleyebilirsiniz. **Link Products** adımında, **Associated products** bölümü bu para birimini kazandıran ürünleri listeler. Ürün eklemek için **Add associated products** seçeneğine tıklayın ve ardından bir ürün seçin. Her grant, kullanıcının bakiyesini sıfırlamak yerine üstüne ekler; bu sayede farklı ürünlerden gelen krediler birikir. Kredi ayarları ürün türüne göre değişir: - **Abonelik ürünleri** için üç kredi ayarı bulunur: - **Credit per cycle** (zorunlu): Her yenileme döngüsünde, deneme süresinin ücretli aboneliğe dönüştüğü yenileme dahil olmak üzere, verilen krediler. - **Credit on trial start** (isteğe bağlı): Ücretsiz deneme başladığında bir kez verilen ayrı bir miktar. - **Credits expire at the end of each billing cycle** (geçiş): Açıkken, Adapty her yenileme döngüsünde yeni döngünün kredilerini eklemeden önce kullanılmamış kredileri sıfırlar. Kapalıyken, krediler döngüler boyunca birikir ve hiçbir zaman sona ermez. - **Tek seferlik ürünler**: Her satın alımda verilen kredi sayısı olan **Credit amount** değerini ayarlayın. Tek seferlik kredilerin süresi hiçbir zaman dolmaz. **Kaydet**'e tıklayarak para birimini ve ürün bağlantılarıyla birlikte oluşturun. Ürün bağlantıları yalnızca ileriye dönük olarak geçerlidir. Yeni bağlanan bir ürün, bir sonraki satın alma veya yenileme işleminden itibaren kredi sağlar. Adapty, mevcut abonelere para birimini otomatik olarak vermez — önce aboneliklerini yenilemeleri gerekir. Bir bağlantıyı kaldırdığınızda gelecekteki krediler durur, ancak daha önce verilen krediler kalır. Süre sonu geçişi açık olduğunda, süresi dolan krediler abonelik yaşam döngüsünü takip eder: - Faturalama yeniden denemesi veya ek süre boyunca Adapty yeni kredi vermez. - İptalin ardından, krediler ödenen dönemin sonuna kadar geçerliliğini korur. - Abonelik sona erdiğinde Adapty kalan kredileri 0'a sıfırlar. ## Sonraki adımlar \{#next-steps\} Bir para birimi oluşturup ürünleri bağladıktan sonra satın alımlar otomatik olarak kredi kazandırır. Buradan itibaren: - Her kullanıcının bakiyesini [Sanal para birimi bakiyesi](virtual-currency-balance) sayfasından takip edin. - Sunucu tarafı API aracılığıyla çalışma zamanında bakiye ekleyin, harcayın ve okuyun: [Sanal para birimi işlemi oluştur](api-adapty/operations/createVirtualCurrencyTransaction) ve [Sanal para birimi bakiyelerini listele](api-adapty/operations/listVirtualCurrencyBalances). Uygulamalı bir örnek için [Sanal para birimi hızlı başlangıç](virtual-currency-quickstart) rehberini takip edin. --- # File: virtual-currency-balance --- --- title: "Sanal para birimi bakiyesi" description: "Bir kullanıcının profilindeki sanal para birimi bakiyelerini görün ve her bakiye değişikliğini etkinlik geçmişinde inceleyin." --- :::link Ana makale: [Sanal para birimleri](virtual-currencies) ::: [Profiles/CRM](profiles-crm) içindeki her kullanıcı profili, o kullanıcının sanal para birimi bakiyesini ve her değişikliğin geçmişini gösterir. ## Kullanıcı profilinde bakiyeleri görüntüleme \{#view-balances-in-a-user-profile\} Kullanıcının [profilini](https://app.adapty.io/profiles/users) açın. **Virtual currency** kartı, kullanıcının sahip olduğu her para birimini listeler. Her satırda şunlar gösterilir: - Para biriminin `COINS` gibi **kodu**. - Tam sayı olarak güncel **bakiye**. Kullanıcı kredi kazandıkça, harcadıkça veya aldıkça bakiyeler güncellenir. Bakiye 0'ın altına inemez: kullanıcının sahip olduğundan fazlasını harcamaya çalışan bir işlem `insufficient_balance` hatasıyla başarısız olur ve hiçbir şey değişmez. Bakiyesi olmayan bir profil boş bir kart gösterir. Bir bakiyeyi kendi kodunuzdan okumak için sunucu tarafı API'sindeki [Sanal para birimi bakiyelerini listele](api-adapty/operations/listVirtualCurrencyBalances) çağrısını kullanın. ## Bakiye değişikliklerini olay geçmişinde inceleme \{#review-balance-changes-in-the-event-history\} Her bakiye değişikliği, profilin olay geçmişinde en yeniden en eskiye sıralanarak gösterilir. Her giriş, değişikliğin adını ve etkilenen para birimlerini listeler. Geçmişte üç tür sanal para birimi olayı görünür: - **Virtual currency credited**: Bir satın alma, yenileme veya deneme başlangıcı kredi sağladı. - **Virtual currency transaction**: Sunucu taraflı bir API çağrısı bakiyeye kredi ekledi veya düşürdü. - **Virtual currency expired**: Süresi dolan krediler, bir faturalama döngüsünün sonunda ya da abonelik sona erdiğinde sıfırlandı. Her giriş, değiştirdiği her para birimi için şunları listeler: - **Virtual currency**: Para birimi adı ve kodu, örneğin `Gold Coins (COINS)`. - **Amount**: İşaretli değişim miktarı — kredi için pozitif, borç için negatif. - **Balance after**: Değişim uygulandıktan sonraki para birimi bakiyesi. Tek bir event birden fazla para birimini aynı anda değiştirebilir — örneğin, aralarında dönüşüm yapmak için bir para biriminden borç alıp diğerine kredi ekleyen tek bir [işlem](api-adapty/operations/createVirtualCurrencyTransaction). ## Bakiyeler, profiller ve cihazlar \{#balances-profiles-and-devices\} Bir bakiye her zaman tam olarak bir [profile](profiles-crm) ait olur ve hiçbir zaman başka birine taşınmaz. Adapty, bakiyeleri profiller arasında paylaşmaz veya aktarmaz; [kullanıcı hesapları arasında access level paylaşımı](profiles-crm#sharing-paid-access-between-user-accounts) yapıldığı gibi bir işlem söz konusu değildir. Pratikte bu şu anlama gelir: - **Tanımlı kullanıcılar**: Bir müşteri kullanıcı kimliği her zaman aynı profile çözümlenir, dolayısıyla kullanıcı giriş yaptığı her cihazda aynı bakiyeyi görür. - **Anonim kullanıcılar**: Anonim bir profil kredi kazanabilir ve harcayabilir, ancak yalnızca tek bir cihazda var olur. Aynı kullanıcı uygulamanızı başka bir cihazda giriş yapmadan açtığında, Adapty sıfır bakiyeli yeni bir anonim profil oluşturur. Sanal para birimi ekonomisini cihazlar arasında çalıştırmak için kullanıcılarınızı tanımlamanız gerekir. Bunu uygulama kodunda SDK aracılığıyla yapabilirsiniz (hızlı başlangıç kılavuzundaki [Kullanıcıları tanımlayın](ios-quickstart-identify) bölümüne bakın) ya da arka ucunuzdan [sunucu taraflı API](getting-started-with-server-side-api) aracılığıyla gerçekleştirebilirsiniz. Bir kullanıcıyı geç tanımlamanın kendine özgü bir sorunu vardır: Kullanıcı anonim olarak kredi kazanır ve ardından başka bir profile ait olan bir müşteri kullanıcı kimliğiyle giriş yaparsa, cihaz o profile ve bakiyesine geçer. Anonim olarak kazanılan krediler eski profilde kalır ve erişilemez hale gelir. Müşteri kullanıcı kimliği yeniyse mevcut profile bağlanır ve kullanıcı bakiyesini korur. Güvenli olmak için, kullanıcıları kredi kazanabilecekleri veya satın alabilecekleri işlemlerden önce tanımlayın. [Sunucu tarafı API](getting-started-with-server-side-api) çağrılarında, profili `adapty-profile-id` veya `adapty-customer-user-id` başlığıyla tanımlayın — her ikisi de tek bir profile çözümlenir. Anonim profiller için `adapty-profile-id` kullanın. --- # File: app-store-offers --- --- title: "App Store'daki Teklifler" description: "Kullanıcı elde tutma oranını artırmak için App Store tekliflerini ayarlayın ve yönetin." --- :::info Bu kılavuzu takip etmeden önce [mağaza ürünlerinizi](quickstart-products) yapılandırın. ::: App Store'daki teklifler, otomatik yenilenen abonelikler için özel fırsatlar, denemeler veya indirimlerdir. Bunlar; yeni kullanıcı çekmeye ve dönüşümü artırmaya yardımcı olan indirimler ve paket tekliflerini kapsar. App Store'da dört farklı teklif türü bulunur ve Adapty bunların tümünü destekler: - **[Başlangıç teklifleri](#introductory-offers) yeni kullanıcılar için**: - Ücretsiz veya indirimli abonelik dönemleri - Yalnızca yeni kullanıcılar uygundur (daha önce başlangıç teklifi etkinleştirmemiş veya aboneliği olmamış kullanıcılar) - Bunları Adapty'de ürünlere bağlamanız gerekmez. Adapty, ürünü satın alan uygun kullanıcılara teklifleri otomatik olarak uygular. - **[Promosyon](#promotional-offers) ve [geri kazanma](#win-back-offers) teklifleri**: - Adapty bu teklifleri satın alma sırasında otomatik olarak uygular; ancak önce ürünlerinizde ve paywalllerinizde teklifleri yapılandırmanız gerekir. - Promosyon teklifleri ücretsiz abonelik dönemleri, yüzde indirimleri ve sabit fiyat indirimlerini kapsar. Her kullanıcı uygun olabilir. - Geri kazanma teklifleri ücretsiz abonelik dönemleri veya yüzde indirimlerini kapsar. Yalnızca ayrılan kullanıcılar uygundur. - **Teklif kodları**: Daha fazla bilgi için bkz. [iOS'ta teklif kodlarını kullanma](making-purchases#redeem-offer-codes-in-ios). :::important App Store tekliflerini kullanmak için [abonelik anahtarınızı](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) Adapty Kontrol Paneli'ne yükleyin. ::: ## Başlangıç teklifleri \{#introductory-offers\} Adapty, kullanıcı uygunsa iOS'ta başlangıç tekliflerini otomatik olarak uygular. Sattığınız ürünler için başlangıç tekliflerini etkinleştirmek üzere yalnızca App Store Connect'te oluşturmanız yeterlidir: 1. App Store Connect'te uygulamanızı açın ve **Monetization > Subscriptions** bölümüne geçin. 2. Bir abonelik grubu seçin ve ihtiyacınız olan aboneliğe gidin. Aboneliğin yapılandırılmış bir süresinin olması gerekir. 3. **View all Subscription Pricing** seçeneğine tıklayın ve **Introductory offers** sekmesine geçin. **Set up introductory offer** seçeneğine tıklayın. 4. Başlangıç teklifinin geçerli olacağı ülke ve bölgeleri seçin. 5. Başlangıç teklifi için başlangıç ve bitiş tarihlerini seçin. Başlangıç teklifinin belirli bir bitiş tarihi yoksa **No end date** seçeneğini işaretleyin. **Next** seçeneğine tıklayın. 6. Başlangıç teklifi türünü seçin. Seçiminize bağlı olarak teklif süresini ve fiyatını da belirlemeniz gerekir. Daha fazla bilgi için [Apple belgelerine](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-introductory-offers-for-auto-renewable-subscriptions) bakın. 7. Seçiminizi gözden geçirin ve **Confirm** seçeneğine tıklayın. Bu kurulumu tamamladıktan sonra Adapty'de herhangi bir şey yapmanıza gerek yoktur. Teklif, ürünü satın alan uygun kullanıcılar için otomatik olarak etkinleşir. Bu ürünü içeren paywall'ı yalnızca teklife uygun kullanıcılara gösterdiğinizden emin olun. ## Promosyon teklifleri \{#promotional-offers\} Adapty, kullanıcılar uygunsa promosyon tekliflerini otomatik olarak uygular. Önce App Store Connect'te tekliflerinizi yapılandırın, ardından bunları Adapty'de bir ürüne ve paywall'a ekleyin: 1. App Store Connect'te uygulamanızı açın ve sol menüden **Monetization > Subscriptions** bölümüne geçin. 2. Bir abonelik grubu seçin ve ihtiyacınız olan aboneliğe gidin. Aboneliğin yapılandırılmış bir süresinin olması gerekir. 3. **View all Subscription Pricing** seçeneğine tıklayın ve **Promotional offers** sekmesine geçin. **Set up promotional offer** seçeneğine tıklayın. 4. Promosyon teklifi ayrıntılarını ayarlayın. Bu değerler oluşturulduktan sonra değiştirilemez ve yeniden kullanılacaktır; bu nedenle dikkatli seçin. - **Promotional offer reference name**: Promosyon teklifi adı. Kullanıcılarınıza görünmeyecektir. - **Promotional offer identifier**: Promosyon teklifi kimlik kodu. Teklifi Adapty'ye eklemek için kullanacaksınız. 5. Promosyon teklifi türünü seçin. Tür, kullanıcıların indirimli fiyat ödeyip ödemeyeceğini ya da ücretsiz dönem alıp almayacağını belirler. İndirim için **Pay as you go** veya **Pay up front** seçin. Ücretsiz abonelik dönemi için **Free** seçin. Ardından teklif süresini ve fiyatını belirleyin. Daha fazla bilgi için [Apple belgelerine](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-promotional-offers-for-auto-renewable-subscriptions) bakın. 6. Gerekirse farklı ülke ve bölgeler için farklı fiyatlar belirleyin ve **Next** seçeneğine tıklayın. 7. Seçiminizi gözden geçirin ve **Confirm** seçeneğine tıklayın. 8. [Promosyon teklifini](create-offer) Adapty'ye ekleyin. ## Geri kazanma teklifleri \{#win-back-offers\} :::important Geri kazanma teklifi oluşturabilmek için aboneliğinizin App Review tarafından onaylanmış olması gerekir. ::: Adapty, kullanıcılar uygunsa geri kazanma tekliflerini otomatik olarak uygular. Önce App Store Connect'te tekliflerinizi yapılandırın, ardından bunları Adapty'de bir ürüne ve paywall'a ekleyin: 1. App Store Connect'te uygulamanızı açın ve sol menüden **Monetization > Subscriptions** bölümüne geçin. 2. Bir abonelik grubu seçin ve ihtiyacınız olan aboneliğe gidin. Aboneliğin yapılandırılmış bir süresinin olması gerekir. 3. **View all Subscription Pricing** seçeneğine tıklayın ve **Win-back offers** sekmesine geçin. **Create offer** seçeneğine tıklayın. 4. Geri kazanma teklifi ayrıntılarını ayarlayın. Bu değerler oluşturulduktan sonra değiştirilemez. - **Reference name**: Teklif adı. Kullanıcılarınıza görünmeyecektir. - **Offer identifier**: Teklif kimlik kodu. Teklifi Adapty'ye eklemek için kullanacaksınız. 5. Teklif türünü, süresini ve fiyatını yapılandırın. Daha fazla bilgi için [Apple belgelerine](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-win-back-offers) bakın. 6. Seçiminizi gözden geçirin ve **Confirm** seçeneğine tıklayın. 7. [Teklifi](create-offer) Adapty'ye ekleyin. ## Sonraki adımlar \{#next-steps\} Teklifleri ekledikten sonra kuruluma devam edin: - **Google Play uygulamanız** da varsa, [Google Play tekliflerini](google-play-offers) ayarlayın. - **Promosyon veya geri kazanma teklifleriniz** varsa, [bunları Adapty'ye ekleyin](create-offer). - Yalnızca **başlangıç teklifleriniz** varsa ve promosyon ya da geri kazanma teklifiniz yoksa her şey hazır demektir. Yine de [Adapty tekliflerle nasıl çalışır?](create-offer#how-adapty-works-with-offers) bölümüne göz atmak işinize yarayabilir. --- # File: google-play-offers --- --- title: "Google Play'de Teklifler" description: "Uygulama monetizasyonunu ve elde tutma oranını artırmak için Google Play tekliflerini yapılandırın." --- Google Play'de her türlü teklif (ücretsiz deneme veya indirimli ödeme) **teklif** olarak eklenir. Teklif oluşturmak için önce bir abonelik oluşturmanız ve otomatik yenilenen bir temel plan eklemeniz gerekir. Teklifler her zaman aboneliklerdeki temel planlar için oluşturulur. Aşağıdaki ekran görüntüsünde, iki temel plana sahip bir `premium_access`(1) aboneliği görebilirsiniz: `1-month` (2) ve `1-year` (3). <img src="/assets/shared/img/c0b1dfa-001930-November-03-XYnbieeu.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Google Play Console'da teklif oluşturmak için: 1. **Add offer** seçeneğine tıklayın ve listeden temel planı seçin. <img src="/assets/shared/img/75a5d69-eb0bc9a-001931-November-03-eQdthUMx.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Teklif ID'sini girin. Bu ID daha sonra analitik ve Adapty kontrol panelinde kullanılacağından anlamlı bir isim verin. <img src="/assets/shared/img/ff282c2-c0b1dfa-001930-November-03-XYnbieeu.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Uygunluk kriterini seçin: 1. **New customer acquisition**: Teklif, yalnızca bu teklifi daha önce kullanmamış yeni abonelere sunulur. En yaygın seçenektir ve varsayılan olarak kullanılmalıdır. 2. **Upgrade**: Bu teklif, başka bir abonelikten yükseltme yapan kullanıcılara sunulur. Mevcut abonelerinizi daha pahalı planlara yönlendirmek istediğinizde kullanın; örneğin bronze katmandan gold katmana geçiş yapan kullanıcılar için. 3. **Developer determined**: Bu teklifi kimin kullanabileceğini uygulama kodundan kontrol edebilirsiniz. Olası dolandırıcılığı önlemek için üretim ortamında dikkatli kullanın: Kullanıcılar ücretsiz veya indirimli aboneliği tekrar tekrar etkinleştirebilir. Bu teklif türü için iyi bir kullanım senaryosu, ayrılmış aboneleri geri kazanmaktır. <img src="/assets/shared/img/ee302dc-a506e5a-001934-November-03-TVBLOz2L.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Teklifinize en fazla iki fiyatlandırma aşaması ekleyin. Üç aşama türü mevcuttur: 1. **Free trial**: Abonelik, yapılandırılan süre boyunca (en az 3 gün) ücretsiz kullanılabilir. En yaygın teklif türüdür. 2. **Single payment**: Kullanıcılar peşin ödeme yaparsa abonelik daha ucuz olur. Örneğin, normalde aylık plan 9,99 $ iken bu teklif türüyle ilk üç ay toplam 19,99 $'a, yani %30 indirimle satın alınabilir. 3. **Discounted recurring payment**: Abonelik, ilk `n` dönem boyunca daha ucuz olur. Örneğin, normalde aylık plan 9,99 $ iken bu teklif türüyle ilk üç ayın her biri 4,99 $'a, yani %50 indirimle sunulur. Bir teklifin iki aşaması olabilir. Bu durumda birinci aşama Free trial, ikinci aşama ise Single payment veya Discounted recurring payment olmalıdır ve bu sırayla uygulanırlar. <img src="/assets/shared/img/d6267f3-a48f79e-001936-November-03-A13wutRh.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Adapty Paywall Builder ile oluşturulan paywallların, çok aşamalı bir Google abonelik teklifinin yalnızca ilk aşamasını göstereceğini lütfen unutmayın. Ancak kullanıcı ürünü satın aldığında, tüm teklif aşamalarının Google Play'de yapılandırıldığı şekilde uygulanacağından emin olabilirsiniz. ::: 5. Teklifi uygulamada kullanmak için etkinleştirin. <img src="/assets/shared/img/d3fc09b-f149ba6-001937-November-03-MO9Gz3ap.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. [Teklifi Adapty'ye ekleme](create-offer) adımına geçin. :::note Farklı temel planlar için aynı teklif ID'leri kullanılabilir. ::: ## Sonraki adımlar \{#next-steps\} Teklifleri ekledikten sonra kuruluma devam edin: - **App Store'da da uygulamanız varsa** [App Store rehberine](app-store-offers) gidin. - **Yalnızca Google Play'de uygulamanız varsa** teklifleri Adapty'ye eklemek için [bu rehberi](create-offer) takip edin. --- # File: create-offer --- --- title: "Adapty'ye teklif ekleme" description: "Adapty'nin araçlarını kullanarak özel abonelik teklifleri oluşturun ve yönetin." --- Adapty, yeni, mevcut veya kaybedilen abonelere deneme süresi veya indirim sunmanıza olanak tanır. Bunları App Store Connect veya Google Play Console'da ayarladıktan sonra, iki adımda Adapty'ye eklemeniz gerekir: 1. [Adapty'de ürünlere mağazalardan aldığınız teklif ID'lerini kullanarak teklifler ekleyin.](#1-create-offer) 2. [Teklifi bir flow veya paywall'da gösterin.](#2-display-offer) :::warning Başlangıç teklifleri (App Store), kullanıcı uygunsa otomatik olarak uygulanır. Bunları Adapty'deki ürünlere eklemeyin. Bu kılavuz, promosyon tekliflerini (App Store), geri kazanma tekliflerini (App Store) ve tüm Google Play tekliflerini nasıl yapılandıracağınızı açıklar. ::: ## 0. Başlamadan önce \{#0-before-you-start\} Adapty'de teklifleri ayarlamaya başlamadan önce aşağıdakileri kontrol edin: 1. İhtiyacınız olan tüm teklifleri mağazada oluşturmuş olun: - [App Store](app-store-offers) - [Google Play](google-play-offers) 2. Adapty'de [ürünleri](create-product) oluşturmuş ve kimliklerini eklemiş olun. 3. App Store için: [Promosyon teklifleri için uygulama içi satın alma anahtarını](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) yüklemiş olun. ## 1. Adapty'deki ürüne teklif ekleme \{#1-create-offer\} Promosyon teklifinizi (Play Store ve App Store için) veya Geri Kazanma teklifinizi (App Store için) uygulama mağazalarında oluşturduktan sonra, bunu Adapty'ye eklemek oldukça basittir: 1. Adapty'nin ana menüsünden [**Products**](https://app.adapty.io/products) sayfasını açın. Teklif eklemek istediğiniz ürünü bulun. 2. Teklif eklemek istediğiniz ürünü bulun. **Actions** sütununda, ürünün yanındaki **3-dot** düğmesine tıklayın ve **Edit**'i seçin. 3. **Edit product** penceresinde **+** düğmesine tıklayın ve **Add offers**'ı seçin. 4. **Add offer** düğmesine tıklayın. 5. Ürün için teklif ayrıntılarını girin. Teklif alanları şunlardır: - **Offer name**: Adapty'de tanımlamanıza yardımcı olacak bir teklif adı girin. Size uygun herhangi bir ad kullanabilirsiniz. - **App Store Offer type**: Eklediğiniz App Store teklif türünü seçin: Promotional veya Win-back. (Başlangıç tekliflerinin eklenmesine gerek yoktur; uygunsa otomatik olarak uygulanırlar.) - **App Store Offer ID**: [App Store'da belirlediğiniz](app-store-products) teklife ait benzersiz kimlik. - **Play Store Offer ID**: Benzer şekilde, [Play Store'da belirlediğiniz](android-products) teklife ait benzersiz kimlik. :::tip **App Store Offer ID** veya **Play Store Offer ID** alanı aktif değilse, **Products** sekmesine geçin ve bir ürün kimliği seçin. ::: 6. (isteğe bağlı) **Add offer** düğmesine tıklayarak gerekirse daha fazla teklif ekleyin. 7. Teklifleri ürüne eklemek için **Save**'e tıklayın. ## 2. Teklifi göster \{#display-offer\} Bir teklif ürüne eklendikten sonra, kullanıcıların o ürünü gördüğü yerde — bir flow'da veya paywall'da — göster. ### Flow'a teklif ekleme \{#add-offer-to-flow\} [Flow Builder](adapty-flow-builder)'da bir teklif, Products ögesindeki bir ürüne eklenir. Önce ürün ögesini ekleyin ve ürünleri atayın — bkz. [Satın almaları ayarlama](paywall-product-block). Teklif eklemek için: 1. Canvas üzerinde, teklifi göstermesi gereken ürün kartını seçin. 2. Sağ panelde, **Product** altında ürünü seçin, ardından **Select offer (optional)** açılır menüsünden teklifi seçin. ### Paywall'a teklif ekleme \{#add-offer-to-paywall\} :::info **Live** (yayında) durumundaki paywall'lara teklif ekleyemezsiniz. Mevcut bir paywall'a teklif eklemek istiyorsanız, paywall'ı [kopyalayın](duplicate-paywalls) ve yeni paywall'da ürünleri yapılandırın. ::: Bir teklifin uygulamanızın kullanıcıları tarafından bir [paywall](paywalls) içinde görünür ve seçilebilir olması için şu adımları izleyin: 1. Bir paywall oluştururken veya düzenlerken **General** sekmesinde, teklifi eklediğiniz ürünü ekleyin. 2. Bu ürün için daha önce oluşturduğunuz teklifi **Offer** listesinden seçin. Liste yalnızca teklifi olan ürünler için görüntülenir. 3. Gerekirse daha fazla ürün ve teklif ekleyin, ancak her ürün için yalnızca bir teklif ekleyebilirsiniz. ## Adapty'nin tekliflerle çalışma şekli \{#how-adapty-works-with-offers\} Tekliflerin Adapty'de nasıl çalıştığına dair şunları not edin: - Kullanıcı bir teklife uygunsa, Adapty satın alma sırasında yapılandırdığınız teklifi otomatik olarak uygular. - App Store'da bir ürün hem başlangıç teklifi hem de promosyon teklifleri içeriyorsa, uygun kullanıcılar önce başlangıç teklifini alır. Bu süre sona erdikten sonra, kullanıcı promosyon teklifine hâlâ uygunsa ve siz bu teklifi Adapty'de yapılandırdıysanız, kullanıcı ürünü tekrar satın almaya çalıştığında teklif uygulanır. - Tekliflerin nasıl uygulandığı üzerinde daha fazla kontrol istiyorsanız veya belirli durumlarda ürününüzü teklif olmadan satmanız gerekiyorsa birkaç seçeneğiniz bulunur: - App Store veya Google Play Console'da uygunluk kriterlerini yapılandırın - App Store veya Google Play Console'da teklif içermeyen ayrı bir ürün oluşturun - Adapty'de teklif içermeyen ayrı bir ürün oluşturun, her iki ürün varyantını içeren paywalleri bir [placement](placements)'a ekleyin ve hangi paywallin farklı kullanıcılara gösterileceğini kontrol etmek için kitle [segmentlerini](segments) kullanın. Örneğin, **Subscription product** veya **Paid access level** bazında segmentler oluşturabilir ya da kendi mantığınızı uygulamak için [özel nitelikleri](profiles-crm) kullanabilirsiniz. --- # File: create-access-level --- --- title: "Access level oluşturma" description: "Daha iyi kullanıcı segmentasyonu için Adapty'de access level oluşturun ve atayın." --- Access level'lar, belirli ürün ID'lerini koda gömmeden uygulamanızdaki kullanıcıların neler yapabileceğini kontrol etmenizi sağlar. Her ürün, kullanıcının belirli bir access level'a ne kadar süreyle sahip olacağını belirler. Dolayısıyla bir kullanıcı satın alma yaptığında, Adapty uygulamaya belirli bir süre (abonelikler için) ya da sonsuza kadar (süresiz erişim satın almaları için) erişim sağlar. Adapty Kontrol Paneli'nde bir uygulama oluşturduğunuzda, `premium` access level otomatik olarak oluşturulur. Bu, varsayılan access level olarak işlev görür ve silinemez. :::tip Access level'ları programatik olarak [Developer CLI](developer-cli-reference#adapty-access-levels-create) kullanarak da oluşturabilirsiniz. ::: Yeni bir access level oluşturmak için: 1. Adapty ana menüsünden **[Products](https://app.adapty.io/access-levels)** bölümüne gidin, ardından **Access levels** sekmesini seçin. <img src="/assets/shared/img/access-level-list.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Create access level** düğmesine tıklayın. <img src="/assets/shared/img/b8646ca-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create access level** penceresinde bir ID atayın. Bu ID, kullanıcı satın alma yaptığında ek özelliklere erişimi etkinleştirmek için mobil uygulamanızdaki tanımlayıcı görevi görecektir. Ayrıca bu tanımlayıcı, uygulama içinde bir access level'ı diğerlerinden ayırt etmenize yardımcı olur. Kolayca anlayabileceğiniz, açık ve net bir ID seçtiğinizden emin olun. 4. Access level oluşturmayı onaylamak için **Create access level** düğmesine tıklayın. --- # File: assigning-access-level-to-a-product --- --- title: "Ürüne access level atama" description: "Abonelik yönetimini optimize etmek için ürünlere access level atayın." --- Her [Ürün](product), kullanıcıların satın alma sonrasında ilgili kısıtlı içeriğe erişebilmesi için bir access level ile ilişkilendirilmelidir. Adapty, abonelik süresini otomatik olarak belirler ve bu süre access level'ın bitiş tarihi olarak kullanılır. Süresiz bir ürün söz konusu olduğunda, müşteri satın aldığında access level herhangi bir bitiş tarihi olmaksızın süresiz olarak aktif kalır. Bir ürüne access level bağlamak için: 1. [Ürünü yapılandırırken](create-product) **Access Level ID** listesinden access level'ı seçin. <img src="/assets/shared/img/access-level-product.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Save**'e tıklayın. --- # File: give-access-level-to-specific-customer --- --- title: "Belirli bir müşteriye access level verme" description: "Adapty'nin gelişmiş araçlarını kullanarak müşterilere belirli access level'lar atayın." --- Adapty Kontrol Paneli'nden belirli bir müşterinin access level'ını manuel olarak ayarlayabilirsiniz. Bu özellik özellikle destek senaryolarında işe yarar. Örneğin, harika bir yorum bırakan bir kullanıcıya teşekkür olarak premium kullanımını bir hafta uzatmak isteyebilirsiniz. ## Adapty Kontrol Paneli'nde belirli bir müşteriye access level verme \{#give-access-level-to-a-specific-customer-in-the-adapty-dashboard\} 1. Adapty ana menüsünden **[Profiles and Segments](https://app.adapty.io/placements)** bölümüne gidin. <img src="/assets/shared/img/profiles-list.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Erişim vermek istediğiniz müşteriye tıklayın. 3. **Add access level** düğmesine tıklayın. <img src="/assets/shared/img/add-access-level.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Vermek istediğiniz access level'ı ve bu müşteri için ne zaman sona ereceğini seçin. 5. **Apply** düğmesine tıklayın. ## API aracılığıyla belirli bir müşteriye access level verme \{#give-access-level-to-a-specific-customer-via-api\} Adapty API'sini kullanarak sunucunuzdan bir müşteriye access level verme seçeneğiniz de bulunmaktadır. Bu özellik, referans bonusları veya ürünlerinizle ilgili diğer etkinlikler için oldukça kullanışlıdır. Ayrıntılı bilgi için [Sunucu taraflı API ile access level verme](api-adapty/operations/grantAccessLevel) sayfasına bakın. --- # File: local-access-levels --- --- title: "Yerel access level'lar" description: "Geçici kesintiler durumunda access level'ları yönetin." --- :::important Aşağıdakilere dikkat edin: - Yerel access level'lar, Adapty SDK'nın 3.12 sürümünden itibaren desteklenmektedir. - Varsayılan olarak, ek güvenlik için Android'de yerel access level'lar devre dışıdır. Bunlara ihtiyaç duyarsanız SDK etkinleştirme sırasında etkinleştirin: [Android](sdk-installation-android#enable-local-access-levels), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#enable-local-access-levels-android). ::: Yapılandırdığınız her ürüne bağlı bir [**access level**](access-level) bulunur. Kullanıcılarınız bir satın alma işlemi gerçekleştirdiğinde, Adapty SDK bu access level'ı kullanıcı [profiline](profiles-crm) atar; dolayısıyla kullanıcıların uygulamadaki ücretli içeriklere erişip erişemeyeceğini belirlemek için bu access level'ı kullanmanız gerekir. Adapty SDK son derece güvenilirdir ve sunucularının kullanılamaz hale gelmesi çok nadiren yaşanır. Ancak böyle nadir bir durumda bile kullanıcılarınız bunu fark etmez. Bir kullanıcı satın alma işlemi yaparken Adapty yanıt alamazsa SDK, satın almaları doğrudan mağazadan doğrulamaya geçer. Bu sayede access level uygulamada yerel olarak verilir ve bunu etkinleştirmek için ek bir kurulum gerekmez. SDK bunu arka planda otomatik olarak yönetir; kullanıcılar ödedikleri içeriklere her zamanki gibi erişmeye devam eder. Yerel access level'ların nasıl çalıştığına dair şunlara dikkat edin: - Kullanıcılar yeniden çevrimiçi olduğunda işlem bilgileri otomatik olarak Adapty sunucularına iletilir; sunucular bu işlemleri kullanıcı profiline uygular ve güncel profili SDK'ya döndürür. - Veriler iletilene kadar güncel bilgiler Adapty analizlerinde görünmez. - Yerel access level'lar yalnızca Adapty sunucuları çevrimdışı olduğunda çalışır. Aksi takdirde SDK önbelleğe alınmış verileri kullanır. - Yerel access level'lar consumable ürünlerde çalışmaz; ancak bir consumable ürüne Adapty kontrol panelinde abonelik türü (aylık, yıllık, haftalık vb.) atanmışsa bu kural geçerli değildir. --- # File: choose-meaningful-placements --- --- title: "Anlamlı placement'lar seçin" description: "Kullanıcı etkileşimini ve geliri artırmak için Adapty ile flow ve paywall placement'larını optimize edin." --- [Placement'ler oluştururken](create-placement), uygulamanızın mantıksal akışını ve oluşturmak istediğiniz kullanıcı deneyimini göz önünde bulundurmanız önemlidir. Çoğu uygulama, deney yapabilme kapasitesinden ödün vermeden en fazla 5 [placement](placements) içermelidir. Placement'lerinizi nasıl yapılandırabileceğinize dair bir örnek: <img src="/assets/shared/img/placement-flows.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **Onboarding flow:** Bu aşama, kullanıcılarınızın uygulamanızla ilk kez etkileşime geçtiği andır. Flow, onboarding ve paywall placement'larını bir arada kullanarak uygulamanızın değer önerisini tanıtmak için mükemmel bir fırsattır. Aboneliklerin %80'inden fazlası onboarding sürecinde başlatıldığından, burada en kârlı abonelikleri satmaya odaklanmak büyük önem taşır. Adapty ile farklı kitleler için kolayca farklı [flow'lar](adapty-flow-builder), [onboarding'ler](onboardings) ve [paywall'lar](paywalls) oluşturabilir; uygulamanız için en iyi seçeneği bulmak amacıyla A/B testleri çalıştırabilirsiniz. Örneğin, ABD'deki kullanıcılar için bir A/B testi başlatarak onlara %50 oranında daha pahalı abonelikler gösterebilirsiniz. 2. **App settings:** Kullanıcı onboarding sürecinde abone olmadıysa, uygulama içinde bir flow veya paywall placement'ı oluşturabilirsiniz. Bu, uygulama ayarlarında ya da kullanıcı belirli bir hedef eylemi tamamladıktan sonra gösterilebilir. Uygulama içindeki kullanıcılar abone olmayı genellikle daha uzun düşündüğünden, buradaki ürünler onboarding aşamasındakilere kıyasla biraz daha uygun fiyatlı olabilir. 3. **Promo:** Kullanıcı flow veya paywall'ı birden fazla kez gördükten sonra hâlâ abone olmadıysa, bu fiyatların onlar için çok yüksek olduğuna ya da aboneliklere karşı kararsız kaldıklarına işaret edebilir. Bu durumda, en uygun fiyatlı aboneliği ya da hatta süresiz erişim ürününü içeren özel bir teklif sunabilirsiniz. Bu yaklaşım, fiyata duyarlı veya abonelik konusunda şüpheci kullanıcıları satın almaya teşvik etmeye yardımcı olabilir. Çoğu uygulama, kullanıcı yolculuğunu ve dönüşüm ile geliri artırmak için flow'ların, paywall'ların, onboarding'lerin veya A/B testlerinin gösterilebileceği kilit noktaları takip eden benzer bir mantık ve placement'lara sahip olacaktır. Monetizasyon stratejilerinizi denemek ve optimize etmek için her placement'ı yapılandırabilirsiniz. --- # File: create-placement --- --- title: "Placement oluşturma" description: "Adapty'de flow ve paywall performansını artırmak için placement'lar oluşturun ve yönetin." --- Bir [Placement](placements), mobil uygulamanızda flow, paywall, onboarding veya A/B testi gösterebileceğiniz belirli bir konumdur. Örneğin, bir abonelik seçimi başlangıç flow'unda görünebilirken, bir consumable ürün (altın koin gibi) kullanıcının oyunda koini bittiğinde gösterilebilir. Farklı placement'larda veya farklı kullanıcı segmentlerine — Adapty'de "kitle" olarak adlandırılır — aynı ya da farklı flow'ları, paywall'ları, onboarding'leri veya A/B testlerini gösterebilirsiniz. Doğru placement'ı seçmeye dair ipuçları için [Anlamlı placement'lar seçin](choose-meaningful-placements) bölümünü okuyun. :::tip Placement'ları [Developer CLI](developer-cli-reference#adapty-placements-create) kullanarak programatik olarak da oluşturabilirsiniz. ::: :::info Placement oluşturma süreci flow'lar, paywall'lar ve onboarding'ler için benzer olsa da, birden fazla türe hizmet eden tek bir placement oluşturamazsınız — her placement türü farklı metrikler işler. ::: ## Placement oluşturma ve yapılandırma \{#create-and-configure-a-placement\} 1. Adapty ana menüsünden **[Placements](https://app.adapty.io/placements)** bölümüne gidin. Oluşturmak istediğiniz placement türüne göre **Flows**, **Paywalls** veya **Onboardings** sekmesine geçin. 2. **Create placement** düğmesine tıklayın. <img src="/assets/shared/img/create-placement-2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Bir **Placement name** girin. Bu, Adapty Kontrol Paneli'ndeki dahili tanımlayıcıdır. Gerekirse daha sonra düzenleyebilirsiniz. 4. Bir **Placement ID** girin. Bu kimliği, placement'ın [flow'larını](adapty-flow-builder), [paywall'larını](paywalls), [onboarding'lerini](onboardings) ve [A/B testlerini](ab-tests) çağırmak için Adapty SDK'da kullanacaksınız. Her placement için benzersiz olduğundan daha sonra düzenleyemezsiniz. Ardından, placement'a bir flow, paywall, onboarding veya A/B testi atayın. Adapty, [kitleler](audience) — [segmentlere](segments) dayalı kullanıcı gruplarını — destekler; böylece farklı kullanıcı gruplarına farklı içerik gösterebilirsiniz. Hedeflemeye ihtiyacınız yoksa varsayılan *Tüm kullanıcılar* kitlesi herkesi kapsar. :::note Devam etmek için, çalıştırmak istediğiniz bir flow, paywall, onboarding veya A/B testi ile belirtmek istediğiniz bir kitle oluşturduğunuzdan emin olun. ::: 1. **Placements/ Your placement** penceresinde, varsayılan *All users* kitlesi için görüntülenecek bir flow, paywall, onboarding veya A/B testi ekleyin. Bunun için **Run flow**, **Run paywall** veya **Run A/B test** düğmelerinden birine tıklayın (etiket, placement türüne göre değişir), ardından açılır listeden istediğiniz flow, paywall, onboarding veya A/B testini seçin. 2. Farklı kullanıcı gruplarına özel içerik oluşturmak için placement'ta birden fazla kitle kullanmak istiyorsanız, **Add audience** düğmesine tıklayın ve listeden istediğiniz kullanıcı segmentini seçin. <Zoom> <img src="/docs/img/placement-add-audience.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Şimdi bu kitle için gösterilecek flow, paywall, onboarding veya A/B testini ekleyin. 4. İhtiyacınız kadar kitle ekleyin. 5. Birden fazla kitleniz varsa, kitlelerin doğru önceliklere sahip olduğunu kontrol edin. 6. **Save and publish** düğmesine tıklayın. Placement'ınız kaydedilip yayınlandıktan sonra ihtiyacınız olan her şey hazır — uygulamanızın kodunda içeriği çekip görüntülemek için **Placement ID**'yi kullanın. ## Sonraki adımlar \{#next-steps\} Uygulamanızda paywall'ları görüntüleme: [iOS](ios-present-paywalls) | [Android](android-present-paywalls) | [React Native](react-native-present-paywalls) | [Flutter](flutter-present-paywalls) | [Unity](unity-present-paywalls) | [Kotlin Multiplatform](kmp-present-paywalls) | [Capacitor](capacitor-present-paywalls) Uygulamanızda onboarding'leri görüntüleme: [iOS](ios-present-onboardings) | [Android](android-present-onboardings) | [React Native](react-native-present-onboardings) | [Flutter](flutter-present-onboardings) | [Unity](unity-present-onboardings) | [Kotlin Multiplatform](kmp-present-onboardings) | [Capacitor](capacitor-present-onboardings) --- # File: edit-placement --- --- title: "Placement düzenleme" description: "Kullanıcı etkileşimini ve paywall görünürlüğünü optimize etmek için Adapty'de placement'ları nasıl düzenleyeceğinizi öğrenin." --- Bir [Placement](placements), mobil uygulamanızda bir flow, paywall, onboarding veya A/B testinin gösterilebileceği belirli bir konumu tanımlar. Örneğin, bir abonelik seçimi başlangıç flow'unda gösterilebilirken, bir consumable ürün (altın para gibi) kullanıcının oyunda parası bittiğinde sunulabilir. Aynı veya farklı flow'ları, paywall'ları, onboarding'leri veya A/B testlerini, Adapty'de kitle (audience) olarak adlandırılan birden fazla placement veya kullanıcı segmentinde gösterme esnekliğine sahipsiniz. Mevcut bir placement'ı düzenlemek için: 1. Adapty ana menüsünden **[Placements](https://app.adapty.io/placements)** bölümüne gidin. Düzenlemek istediğiniz placement türüne göre **Flows**, **Paywalls** veya **Onboardings** sekmesine geçin. 2. Düzenlemek istediğiniz placement'a tıklayın. 3. Sağ üst köşedeki **Edit placement** düğmesine tıklayın. 4. Gerekli değişiklikleri yapın. Bu penceredeki seçenekler hakkında daha fazla bilgi için [Placement oluşturma](create-placement) bölümünü okuyun. 5. Değişiklikleri onaylamak için **Save and publish** düğmesine tıklayın. --- # File: export-placements --- --- title: "Placement dışa aktarma" description: "Kullanıcı etkileşimini ve paywall görünürlüğünü optimize etmek için Adapty'de placement'ları nasıl dışa aktaracağınızı öğrenin." --- Birden fazla flow, paywall ve onboarding ile çalışırken, hangilerinin hangi kullanıcılara gösterildiğini takip etmek önemlidir. Her kitle için hangi flow/paywall/onboarding'in göründüğünü görmek ve değişiklikler yapıp denemeler yürüttükten sonra ayarlarınızı gözden geçirmek için tüm [placement](placements) ayarlarınızı bir CSV dosyasına aktarabilirsiniz. :::tip Daha pratik buluyorsanız, [placement'ları sunucu taraflı API kullanarak dışa aktarabilirsiniz](api-export-analytics/operations/retrievePlacementInfo). ::: Flow, paywall veya onboarding placement'larını dışa aktarmak için: 1. Ana menüden **[Placements](https://app.adapty.io/placements)** bölümüne gidin. **Flows**, **Paywalls** veya **Onboardings** sekmesine geçin; her tür için placement'lar ayrı ayrı dışa aktarılır. 2. **Export to CSV** düğmesine tıklayın. <img src="/assets/shared/img/export-placement.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Dışa aktarılan CSV dosyası, placement'larınız hakkında aşağıdaki bilgileri içerir: - Placement ID - Placement adı - Kitle adı - Segment adı - Placement'lar arası A/B testi adı - A/B testi adı - Flow adı, Paywall adı veya Onboarding adı (dışa aktardığınız sekmeye bağlı olarak) :::note Placement'lar arası A/B testleri, flow placement'ları için desteklenmez; bu nedenle söz konusu sütun flow dışa aktarmalarında boş görünecektir. ::: --- # File: delete-placement --- --- title: "Placement'ı sil" description: "Adapty'de flow veya paywall performansınızı etkilemeden bir placement'ı nasıl sileceğinizi öğrenin." --- [Placement](placements), mobil uygulamanızda bir flow, paywall, onboarding veya A/B testinin gösterilebildiği belirli bir konumu ifade eder. :::danger Herhangi bir placement'ı silme seçeneğiniz olsa da, mobil uygulamanızda aktif olarak kullanılan bir placement'ı silmemeniz kritik önem taşır. Aktif bir flow veya paywall placement'ını silmek, [kurulumu yaptıysanız](fallback-paywalls) yedek paywallın kalıcı olarak gösterilmesine yol açar ve yayınlanmış uygulama sürümlerinde artık dinamik bir flow veya paywall ile değiştirmeniz mümkün olmaz. ::: Mevcut bir placement'ı silmek için: 1. Adapty ana menüsünden **[Placements](https://app.adapty.io/placements)** bölümüne gidin. Silmek istediğiniz placement türüne göre **Flows**, **Paywalls** veya **Onboardings** sekmesine geçin. 2. Placement'ın yanındaki **3 nokta** düğmesine tıklayın ve **Delete** seçeneğini seçin. <img src="/assets/shared/img/delete-placement.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Açılan **Delete placement** penceresinde, silmek üzere olduğunuz placement'ın adını girin. <img src="/assets/shared/img/8177c51-delete_placement.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Silme işlemini onaylamak için **Delete forever** düğmesine tıklayın. --- # File: add-audience-paywall-ab-test --- --- title: "Placement'a kitle ve flow, paywall veya A/B testi ekleme" description: "Adapty'de farklı kitle segmentleri için flow'lar ve paywall'lar üzerinde A/B testleri çalıştırın." --- :::note Devam etmek için, çalıştırmak istediğiniz bir flow, paywall, onboarding veya A/B testi ile belirtmek istediğiniz bir kitle oluşturduğunuzdan emin olun. ::: 1. **Placements/ Your placement** penceresinde, varsayılan *All users* kitlesi için görüntülenecek bir flow, paywall, onboarding veya A/B testi ekleyin. Bunun için **Run flow**, **Run paywall** veya **Run A/B test** düğmelerinden birine tıklayın (etiket, placement türüne göre değişir), ardından açılır listeden istediğiniz flow, paywall, onboarding veya A/B testini seçin. 2. Farklı kullanıcı gruplarına özel içerik oluşturmak için placement'ta birden fazla kitle kullanmak istiyorsanız, **Add audience** düğmesine tıklayın ve listeden istediğiniz kullanıcı segmentini seçin. <Zoom> <img src="/docs/img/placement-add-audience.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Şimdi bu kitle için gösterilecek flow, paywall, onboarding veya A/B testini ekleyin. 4. İhtiyacınız kadar kitle ekleyin. 5. Birden fazla kitleniz varsa, kitlelerin doğru önceliklere sahip olduğunu kontrol edin. 6. **Save and publish** düğmesine tıklayın. Adapty'deki **Kitleler**, [segmentler](segments) ile tanımlanmış kullanıcı gruplarıdır. Flow'ları, paywall'ları, onboarding'leri ve A/B testlerini yalnızca ilgili kullanıcılara göstermeni sağlar. Her grubun doğru içeriği görmesi için segmentleri filtrelerle oluşturabilirsin. Bir [placement](placements)'a kitle eklediğinde, flow'ları, paywall'ları, onboarding'leri veya A/B testlerini belirli bir kullanıcı grubuna hedeflersin. Bir kitleyi placement'a bağlamak, doğru kullanıcıların uygulama yolculuklarının doğru anında doğru içeriği görmesini sağlar. Bir flow, paywall, onboarding veya A/B testi eklemek istediğiniz placement'ı açın ya da [Placements](https://app.adapty.io/placements) menüsünden yeni bir tane oluşturun. :::note Devam etmek için, çalıştırmak istediğiniz bir flow, paywall, onboarding veya A/B testi ile belirtmek istediğiniz bir kitle oluşturduğunuzdan emin olun. ::: 1. **Placements/ Your placement** penceresinde, varsayılan *All users* kitlesi için görüntülenecek bir flow, paywall, onboarding veya A/B testi ekleyin. Bunun için **Run flow**, **Run paywall** veya **Run A/B test** düğmelerinden birine tıklayın (etiket, placement türüne göre değişir), ardından açılır listeden istediğiniz flow, paywall, onboarding veya A/B testini seçin. 2. Farklı kullanıcı gruplarına özel içerik oluşturmak için placement'ta birden fazla kitle kullanmak istiyorsanız, **Add audience** düğmesine tıklayın ve listeden istediğiniz kullanıcı segmentini seçin. <Zoom> <img src="/docs/img/placement-add-audience.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Şimdi bu kitle için gösterilecek flow, paywall, onboarding veya A/B testini ekleyin. 4. İhtiyacınız kadar kitle ekleyin. 5. Birden fazla kitleniz varsa, kitlelerin doğru önceliklere sahip olduğunu kontrol edin. 6. **Save and publish** düğmesine tıklayın. --- # File: change-audience-priority --- --- title: "Placement'ta kitle önceliğini değiştirme" description: "Kullanıcılara kişiselleştirilmiş teklifler sunmak için Adapty'de kitle önceliklerini ayarlayın." --- Bir [placement](placements) içinde farklı kullanıcı kitleleri tanımladığınızda, bir kullanıcı birden fazla kitlenin üyesi olabilir. Örneğin "Beginners" (Yeni Başlayanlar), "Runners" (Koşucular) ve "All users" (Tüm Kullanıcılar) gibi kitleler oluşturduysanız, bir kullanıcı birden fazla kategoriye girdiğinde hangi kitlenin önce dikkate alınacağını belirlemeniz gerekir. <img src="/assets/shared/img/afee54f-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu noktada kitle önceliği devreye girer. Kitle önceliği sayısal bir sıralamadır; #1 en yüksek önceliği temsil eder. Hangi kitlenin önce kontrol edileceğini bu sıralama belirler. Kısaca söylemek gerekirse, kitle önceliği Adapty'nin hangi paywall, onboarding veya A/B testinin gösterileceğine karar verirken hangi kitleyi önce uygulayacağını yönetir. Bir kitlenin önceliği düşükse, o kitleye girebilecek kullanıcılar atlanabilir ve daha yüksek öncelikli başka bir kitleye yönlendirilebilir. Crossplacement kitleleri, yani [crossplacement A/B testleri](ab-tests#ab-test-types) için oluşturulanlar, her zaman normal kitlelerden önce gelir. "All users" kitlesinin önceliği her zaman en düşüktür; çünkü bu kitle, diğer hiçbir kitleyle eşleşmeyen herkesi kapsayan bir geri dönüş kitlessidir. Bir placement için kitle önceliklerini ayarlamak üzere: 1. Yeni bir placement oluştururken veya mevcut birini düzenlerken **Edit priority** düğmesine tıklayın. Bu düğme yalnızca placement'a en az üç kitle eklendiğinde ("All users" ve iki başka kitle) görünür. Daha az kitle varsa sıralama zaten bellidir; "All users" kitlesinin her zaman en sona geldiği aşikardır. <img src="/assets/shared/img/edit-priority.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Açılan **Edit audience priorities** penceresinde, kitleleri doğru sıraya getirmek için sürükleyip bırakın. <img src="/assets/shared/img/reorder_audiences.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Save** düğmesine tıklayın. --- # File: placement-metrics --- --- title: "Placement metrikleri" description: "Paywall performansını artırmak için Adapty'deki placement metriklerini analiz edin." --- Adapty ile uygulamanızda birden fazla placement oluşturabilir ve yönetebilirsiniz; her placement farklı paywall'lar veya A/B testleriyle ilişkilendirilebilir. Bu esneklik sayesinde belirli kullanıcı segmentlerini hedefleyebilir, farklı teklifler veya fiyatlandırma modelleri üzerinde deneyler yapabilir ve uygulamanızın para kazanma stratejisini optimize edebilirsiniz. Placement'larınızın performansı ve kullanıcıların tekliflerinizle etkileşimi hakkında değerli bilgiler edinmek için Adapty, görüntülenen paywall'larla ilgili çeşitli kullanıcı etkileşimlerini ve işlemleri izler. Güçlü analitik sistemi; görüntülemeler, tekil görüntülemeler, satın almalar, denemeler, iadeler, dönüşüm oranları ve gelir gibi metrikleri yakalar. Toplanan metrikler gerçek zamanlı olarak sürekli güncellenir ve Adapty'nin kullanıcı dostu kontrol paneli aracılığıyla kolayca erişilip analiz edilebilir. Analiz için zaman aralığını özelleştirebilir, farklı parametrelere göre filtreler uygulayabilir ve çeşitli placement'lar, kullanıcı segmentleri veya ürünler arasında metrikleri karşılaştırabilirsiniz. Placement metrikleri, tüm placement'larınızın performansına genel bir bakış sunan placement listesinde mevcuttur. Bu üst düzey görünüm, her placement için toplu metrikler sunarak performanslarını karşılaştırmanıza ve trendleri belirlemenize olanak tanır. Her bir placement'ın daha ayrıntılı analizini yapmak için placement ayrıntı metriklerine gidebilirsiniz. Bu sayfada, seçilen placement'a özel kapsamlı metrikler bulacaksınız. Bu metrikler, belirli bir placement'ın nasıl performans gösterdiğine dair daha derin içgörüler sunarak etkinliğini değerlendirmenizi ve veriye dayalı kararlar almanızı sağlar. <img src="/assets/shared/img/3e711fc-CleanShot_2023-07-26_at_14.55.042x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Kurulum tarihine göre metrikleri filtrele \{#filter-metrics-by-install-date\} Paywall, deneme süresi ve satın alma metrikleri iki farklı tarihe göre gruplandırılabilir: - **Etkinlik tarihi** — paywall'ın görüntülendiği, deneme süresinin başladığı veya satın almanın gerçekleştiği tarih. - **Yükleme tarihi** — kullanıcının uygulamayı ilk kez açtığı tarih. Aynı tarih aralığı için bu iki görünüm çok farklı sayılar gösterebilir. **Filter metrics by install date** onay kutusu, kontrol panelinin hangisini kullanacağını belirler: - **İşaretsiz (varsayılan)**: Metrikler etkinlik tarihine göre gruplandırılır. - **İşaretli**: Metrikler yükleme tarihine göre gruplandırılır. **Örnek.** Tarih aralığını 1–30 Nisan olarak ayarlayıp deneme sürelerine bakıyorsunuz. - **İşaretsiz**: O kullanıcıların uygulamayı ne zaman yüklediğinden bağımsız olarak Nisan'da *başlayan* deneme sürelerini gösterir. - **İşaretli**: Deneme sürelerinin ne zaman başladığından bağımsız olarak Nisan'da *yükleme yapan* kullanıcıların deneme sürelerini gösterir. Belirli bir kohort için kullanıcı edinme performansını ölçmek istiyorsanız yükleme tarihi görünümünü kullanın. Belirli bir dönemdeki paywall veya onboarding etkinliğini ölçmek içinse etkinlik tarihi görünümünü tercih edin. ### Metrik kontrolleri \{#metrics-controls\} Sistem, metrikleri seçilen zaman dilimine göre görüntüler ve dört girintili düzeye sahip sol sütun parametresine göre düzenler. #### Metrik verileri için görünüm seçenekleri \{#view-options-for-metrics-data\} Placement metrikleri sayfası, metrik verileri için iki görünüm seçeneği sunar: paywall tabanlı ve kitle tabanlı. <img src="/assets/shared/img/9d26b32-Export-1690376094858.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Paywall tabanlı görünümde metrikler, paywall ile ilişkili placement'lara göre gruplandırılır. Bu sayede kullanıcılar farklı placement'lara göre metrikleri analiz edebilir. Kitle tabanlı görünümde ise metrikler, paywall'ın hedef kitlesine göre gruplandırılır. Kullanıcılar, farklı kitle segmentlerine özgü metrikleri değerlendirebilir. #### Zaman aralıkları \{#time-ranges\} Metrik verilerini analiz etmek için çeşitli zaman aralıkları seçebilirsiniz; günler, haftalar, aylar veya özel tarih aralıkları gibi belirli sürelere odaklanmanızı sağlar. <img src="/assets/shared/img/15d2c3e-CleanShot_2023-07-26_at_16.49.272x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: Adapty, metrik analizini ihtiyaçlarınıza göre özelleştirmek ve filtrelemek için güçlü araçlar sunar. Adapty'nin metrikler sayfasında çeşitli zaman aralıklarına, gruplama seçeneklerine ve filtreleme olanaklarına erişebilirsiniz. - ✅ Şuna göre filtrele: Kitle, paywall, paywall grubu, placement, ülke, mağaza. - ✅ Şuna göre grupla: Segment, mağaza ve ürün #### Tek metrik grafiği \{#single-metrics-chart\} Placement metrik sayfasının temel bileşenlerinden biri, seçilen metrikleri görsel olarak sunan ve analizi kolaylaştıran grafik bölümüdür. Placement metrikleri sayfasındaki grafik bölümü, seçilen metrik değerlerini görsel olarak temsil eden yatay bir çubuk grafik içerir. Grafikteki her çubuk bir metrik değerine karşılık gelir ve boyutu orantılıdır; bu da veriye tek bakışta hızlıca anlaşılmasını sağlar. Yatay çizgi analiz edilen zaman dilimini, dikey sütun ise metriklerin sayısal değerlerini gösterir. Tüm metrik değerlerinin toplamı grafiğin yanında görüntülenir. <img src="/assets/shared/img/4623c5b-Export-1690375597411.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ayrıca grafik bölümünün sağ üst köşesindeki ok simgesine tıklamak görünümü genişletir ve seçilen metrikleri grafiğin tam satırında gösterir. #### Toplam metrik özeti \{#total-metrics-summary\} Tekil metrik grafiğinin yanında toplam metrik özeti bölümü yer alır. Bu bölüm, belirli bir zaman noktasında seçilen metriklerin kümülatif değerlerini gösterir ve açılır menü aracılığıyla görüntülenen metriği değiştirmenize olanak tanır. <img src="/assets/shared/img/0f647cf-CleanShot_2023-07-26_at_14.55.492x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Metrik tanımları \{#metrics-definitions\} Kapsamlı tanımlarımızla placement metriklerinin gücünü keşfedin. Gelirden dönüşüm oranlarına kadar, para kazanma stratejilerinizi güçlendirecek ve uygulamanızın başarısını artıracak değerli içgörüler edinin. <img src="/assets/shared/img/771a0f0-Export-1690375049771.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: #### Gelir \{#revenue\} Bu metrik, belirli placement'lar içindeki satın almalar ve yenilemelerden USD cinsinden elde edilen toplam para miktarını temsil eder. Gelir hesaplamasının Apple App Store veya Google Play Store komisyonunu içermediğini ve herhangi bir ücret düşülmeden önce hesaplandığını lütfen göz önünde bulundurun. #### Hasılat \{#proceeds\} Bu metrik, belirli placement'lar içindeki satın almalar ve yenilemelerden geçerli Apple App Store veya Google Play Store komisyonu düşüldükten sonra uygulama sahibinin USD cinsinden elde ettiği gerçek para miktarını temsil eder. Uygulamanın kazancına doğrudan katkıda bulunan net geliri yansıtır. Hasılatın nasıl hesaplandığına dair daha fazla bilgi için Adapty [dokümantasyonuna](analytics-cohorts#revenue-vs-proceeds) başvurabilirsiniz. #### ARPPU \{#arppu\} ARPPU, ödeme yapan kullanıcı başına ortalama gelir anlamına gelir ve belirli placement'lar içinde ödeme yapan kullanıcı başına üretilen ortalama geliri ölçer. Toplam gelirin benzersiz ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. Örneğin toplam gelir 15.000 $ ve 1.000 ödeme yapan kullanıcı varsa ARPPU 15 $ olur. #### ARPAS \{#arpas\} ARPAS (aktif abone başına ortalama gelir), belirli placement'lar içinde aktif abone başına üretilen ortalama geliri ölçmenizi sağlar. Toplam gelirin deneme veya abonelik başlatan abone sayısına bölünmesiyle hesaplanır. Örneğin toplam gelir 5.000 $ ve 1.000 abone varsa ARPAS 5 $ olur. Bu metrik, abone başına ortalama para kazanma potansiyelini değerlendirmeye yardımcı olur. #### ARPU \{#arpu\} Yalnızca onboarding placement'ları için. ARPU, onboarding'i görüntüleyen kullanıcı başına ortalama gelirdir. Toplam gelirin benzersiz görüntüleyici sayısına bölünmesiyle hesaplanır. #### Satın almalara tekil dönüşüm oranı \{#unique-cr-to-purchases\} Satın almalara tekil dönüşüm oranı, belirli placement'lar içindeki satın alma sayısının benzersiz görüntüleme sayısına bölünmesiyle hesaplanır. Satın almaların benzersiz görüntüleme sayısına oranına odaklanarak, belirli placement'lar içindeki tekil ziyaretçileri ödeme yapan müşterilere dönüştürme etkinliğine dair içgörüler sunar. #### Satın almalara dönüşüm oranı \{#cr-to-purchases\} Satın almalara dönüşüm oranı, belirli placement'lar içindeki satın alma sayısının paywall'ların toplam görüntüleme sayısına bölünmesiyle hesaplanır. Belirli placement'lar içindeki görüntülemelerin yüzde kaçının satın almayla sonuçlandığını gösterir ve paywall'ınızın kullanıcıları ödeme yapan müşterilere dönüştürme etkinliğine dair içgörüler sunar. #### Denemelere tekil dönüşüm oranı \{#unique-cr-to-trials\} Denemelere tekil dönüşüm oranı, belirli placement'lar içinde başlatılan deneme sayısının benzersiz görüntüleme sayısına bölünmesiyle hesaplanır. Belirli placement'lar içindeki benzersiz görüntülemelerin yüzde kaçının deneme aktivasyonuyla sonuçlandığını ölçer ve paywall'ınızın tekil ziyaretçileri deneme kullanıcılarına dönüştürme etkinliğine dair içgörüler sunar. #### Satın almalar \{#purchases\} Satın almalar, belirli placement'lar içindeki paywall'da gerçekleştirilen çeşitli işlemlerin kümülatif toplamını temsil eder. Bu metriğe dahil olan işlemler şunlardır (yenilemeler dahil değildir): - Belirli placement'lar içinde doğrudan yapılan yeni satın almalar. - Başlangıçta belirli placement'lar içinde başlatılan deneme dönüşümleri. - Belirli placement'lar içinde yapılan abonelik düşürme, yükseltme ve çapraz geçişler. - Belirli placement'lar içindeki abonelik geri yüklemeleri; örneğin otomatik yenileme olmaksızın süresi dolan bir aboneliğin yeniden etkinleştirilmesi. Bu farklı işlem türlerini dikkate alarak satın almalar metriği, belirli placement'lar içindeki genel edinim ve para kazanma faaliyetine kapsamlı bir bakış sunar. #### Denemeler \{#trials\} Denemeler metriği, belirli placement'lar içinde başlatılan toplam deneme sayısını temsil eder. Kullanıcıların bu placement'lardaki paywall'ınız aracılığıyla deneme süresi başlattıklarının sayısını gösterir. Bu metrik, deneme teklifinizin etkinliğini izlemenize ve denemeden ücretli aboneliklere kullanıcı etkileşimi ile dönüşüm hakkında içgörüler elde etmenize yardımcı olur. #### İptal edilen denemeler \{#trials-canceled\} İptal edilen denemeler metriği, belirli placement'lar içinde otomatik yenileme özelliğinin kapatıldığı deneme sayısını temsil eder. Bu durum, kullanıcıların denemeden manuel olarak aboneliğini iptal etmesiyle gerçekleşir ve deneme süresi sonrasında aboneliğe devam etmeyeceklerini gösterir. İptal edilen denemeleri izlemek, kullanıcı davranışı hakkında değerli bilgiler sağlar ve belirli placement'lar içinde kullanıcıların denemeden ayrılma oranını anlamanıza olanak tanır. #### İadeler \{#refunds\} İadeler metriği, belirli placement'lar içinde iade edilen satın alma ve abonelik sayısını temsil eder. Buna müşteri talepleri, ödeme sorunları veya geçerli iade politikaları gibi çeşitli nedenlerle iptal edilen ya da iade edilen işlemler dahildir. #### İade oranı \{#refund-rate\} İade oranı, belirli placement'lar içindeki iade sayısının ilk kez yapılan satın alma sayısına bölünmesiyle hesaplanır (yenilemeler dahil değildir). Örneğin 5 iade ve 1.000 ilk kez yapılan satın alma varsa iade oranı %0,5 olur. #### Görüntülemeler \{#views\} Görüntülemeler metriği, belirli placement'lar içindeki paywall'ın kullanıcılar tarafından kaç kez görüntülendiğinin toplam sayısını temsil eder. Bir kullanıcı belirli placement'lardaki paywall'ı her ziyaret ettiğinde bu ayrı bir görüntüleme olarak sayılır. Görüntülemeleri izlemek, paywall'ınızla kullanıcı etkileşiminin ve katılım düzeyinin anlaşılmasına yardımcı olur; kullanıcı davranışı ve uygulamanızın belirli alanlarındaki paywall yerleşimi ile tasarımının etkinliğine dair içgörüler sunar. #### Tekil görüntülemeler \{#unique-views\} Tekil görüntülemeler metriği, belirli placement'lar içindeki paywall'ın kullanıcılar tarafından görüntülendiği benzersiz örnek sayısını temsil eder. Her ziyareti ayrı bir görüntüleme olarak sayan toplam görüntülemelerin aksine, tekil görüntülemeler her kullanıcının belirli placement'lardaki paywall'ı ziyaretini kaç kez eriştiğinden bağımsız olarak yalnızca bir kez sayar. Tekil görüntülemeleri izlemek, belirli placement'lar içinde kullanıcı etkileşiminin ve paywall'ınızın erişiminin daha doğru ölçülmesine yardımcı olur; zira toplam ziyaret sayısı yerine bireysel kullanıcılara odaklanır. #### Tamamlamalar ve tekil tamamlamalar \{#completions--unique-completions\} Yalnızca onboarding placement'ları için. Tamamlamalar, kullanıcıların onboarding placement'ınızı ilk ekrandan son ekrana kadar tamamladıkları sayısını sayar. Birisi iki kez tamamlarsa bu iki **tamamlama** ama bir **tekil tamamlama** sayılır. #### Tekil tamamlama oranı \{#unique-completions-rate\} Yalnızca onboarding placement'ları için. Tekil tamamlama sayısının tekil görüntüleme sayısına bölümüdür. Bu metrik, insanların onboarding placement'ıyla nasıl etkileşim kurduğunu anlamanıza ve onu görmezden geldiklerini fark ettiğinizde değişiklikler yapmanıza yardımcı olur. --- # File: create-paywall --- --- title: "Paywall oluşturma" description: "Adapty'nin Paywall Builder'ı ile yüksek dönüşüm sağlayan paywalllar nasıl oluşturulur, öğrenin." --- [Paywall](paywalls), hangi ürünlerin sunulacağını tanımlayan bir Adapty yapılandırmasıdır. Adapty'de ürünleri uygulamanızda almanın tek yolu paywalllar üzerinden geçer. Paywallı nasıl gösterdiğinizden bağımsız olarak bir paywall oluşturmanız gerekir: - [**Paywall Builder**](adapty-paywall-builder): No-code editörde bir ekran tasarlayın. Adapty bunu render eder ve satın almaları yönetir. - **Özel paywall**: Kendi arayüzünüzü uygulayın ve ürünleri almak için paywall yapılandırmasını kullanın. Oluşturduğunuz paywall'ı bir [placement](placements)'a atayın; placement'lar hangi kullanıcının hangi paywall'ı göreceğini belirler. Yayındaki bir paywall'ın ürünleri sabit olduğundan, metrikleri her zaman aynı kombinasyonu yansıtır ve farklı ürün ile fiyatlandırma setlerinin performansını karşılaştırmanıza olanak tanır. :::tip Ayrıca [Developer CLI](developer-cli-reference#adapty-paywalls-create) kullanarak paywallları programatik olarak da oluşturabilirsiniz. ::: <details> <summary>Paywall oluşturmaya başlamadan önce (Genişletmek için tıklayın)</summary> 1. [En az bir ürün oluşturun](create-product). 2. (isteğe bağlı) [Teklif oluşturun](create-offer). </details> ## Paywall oluşturma \{#create-paywall\} Adapty kontrol panelinde yeni bir paywall oluşturmak için: 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümüne gidin. Bu sayfa tüm paywalllarınıza ve metriklerine genel bir bakış sunar. 2. **Create paywall**'a tıklayın. 3. **Paywalls / New paywall** sayfasında, bu paywall'ı Adapty Kontrol Paneli genelinde tanımlamak için bir **Paywall name** girin. 4. **Add product**'a tıklayın. 5. Kullanıcılarınıza gösterilecek ürünleri seçin. :::note - Bu listedeki ürün sırası SDK'da korunur, dolayısıyla ürünleri istediğiniz sıraya göre düzenleyin. - Bir paywall canlıya alındıktan sonra üzerindeki ürünleri değiştiremezsiniz; bu durum paywall metriklerini etkileyebilir. ::: 6. Ürünleriniz için ücretsiz deneme veya başka teklifler sunuyorsanız bunları buraya ekleyin; aksi takdirde kullanıma açılmazlar. Bu ürün için [daha önce oluşturduğunuz](create-offer) bir teklifi **Offer** listesinden seçin. Liste yalnızca teklifi olan ürünler için görünür. 7. Paywall oluşturmayı onaylamak için **Create as a draft**'a tıklayın. Paywall'ınız artık oluşturuldu! <img src="/assets/shared/img/create-paywall.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '900px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Sonraki adımlar \{#next-steps\} İlk paywall'ınızı oluşturduktan sonra: 1. Bir [placement](placements)'a ekleyin. Placement ID'leri kod içine gömülü tek varlıklar olacaktır. Satılacak ürünleri almak için bunları kullanacaksınız. 2. Paywall ile bundan sonra nasıl çalışacağınız uygulamanıza bağlıdır: - [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanmak istiyorsanız paywall'ı no-code editörde tasarlayın. Adapty, paywall'ı render eder ve satın alma mantığını yönetir; sizin yapmanız gereken tek şey paywall'ı uygulama kodunuzda göstermektir. - Kullanmak istediğiniz özel bir paywall varsa platformunuz için Adapty ile uygulama içi satın alma rehberlerimize bakın: - [iOS](ios-implement-paywalls-manually) - [Android](android-implement-paywalls-manually) - [React Native](react-native-implement-paywalls-manually) - [Flutter](flutter-implement-paywalls-manually) - [Unity](unity-implement-paywalls-manually) - [Kotlin Multiplatform](kmp-implement-paywalls-manually) --- # File: customize-paywall-with-remote-config --- --- title: "Paywall'ı remote config ile tasarla" description: "Adapty'de daha iyi hedefleme için remote config ile paywall'ınızı özelleştirin." --- :::important Bu kılavuz, klasik paywall'lar için remote config'i kapsamaktadır. Flow Builder için [Flow'u remote config ile özelleştirme](customize-flow-with-remote-config) bölümüne bakın. ::: Paywall Remote Config, esnek yapılandırma seçenekleri sunan güçlü bir araçtır. Paywall'larınızı tam anlamıyla özelleştirmek için özel JSON payload'larının kullanımına olanak tanır. Bununla başlıklar, görseller, yazı tipleri, renkler ve daha fazlası gibi çeşitli parametreler tanımlayabilirsiniz. <details> <summary>Paywall özelleştirmeye başlamadan önce (Genişletmek için tıklayın)</summary> 1. [Ürün oluşturun](create-product). 2. [Paywall oluşturun ve ürünü ekleyin](create-paywall). </details> Remote config kullanarak paywall'ı özelleştirmeye başlamak için: 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümünü açın. 2. Paywall'a tıklayarak açın. <img src="/assets/shared/img/remote-config.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Remote config** sekmesine geçin. <img src="/assets/shared/img/remote-config-3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Remote config'in 2 görünümü vardır: - [Tablo](customize-paywall-with-remote-config#table-view-of-the-remote-config) - [JSON](customize-paywall-with-remote-config#json-view-of-the-remote-config) Hem **Table** hem de **JSON** görünümleri aynı yapılandırma öğelerini içerir. Aradaki tek fark kişisel tercihtir; tek işlevsel ayrım, tablo görünümünün lokalizasyon hatalarını düzeltmede işe yarayabilecek bir bağlam menüsü sunmasıdır. Görünümler arasında geçiş yapmak için istediğiniz zaman **Table** veya **JSON** sekmesine tıklayabilirsiniz. Paywallınızı özelleştirmek için hangi görünümü seçmiş olursanız olun, bu verilere daha sonra `AdaptyPaywall`'ın `remoteConfig` veya `remoteConfigString` özelliklerini kullanarak SDK üzerinden erişebilir ve paywallınızda bazı ayarlamalar yapabilirsiniz. Ayrıca [sunucu tarafı API](api-adapty/operations/updatePaywall)'sini kullanarak remote config değerlerini programatik olarak güncelleyebilir ve manuel kontrol paneli güncellemelerine gerek kalmadan paywall yapılandırmalarını dinamik olarak değiştirebilirsiniz. Remote config'i nasıl kullanabileceğinize dair bazı örnekler aşağıda verilmiştir. <Tabs groupId="current-os" queryString> <TabItem value="Titles" label="Başlıklar" default> ```json showLineNumbers { "screen_title": "Today only: Subscribe, and get 7 days for free!" } # Test titles or others texts ``` </TabItem> <TabItem value="Images" label="Görseller" default> ```json showLineNumbers { "background_image": "https://adapty.io/media/paywalls/bg1.webp" } # Test images on your paywall ``` </TabItem> <TabItem value="Fonts" label="Yazı Tipleri" default> ```json showLineNumbers { "font_family": "San Francisco", "font_size": 16 } # Test fonts ``` </TabItem> <TabItem value="Color" label="Renk" default> ```json showLineNumbers { "subscribe_button_color": "purple" } # Test colors of buttons, texts etc. ``` </TabItem> <TabItem value="HTML" label="HTML" default> ```json showLineNumbers { "photo_gallery": "https://adapty.io/media/paywalls/link-to-html-snippet.html" } # Any HTML code that can be displayed on the paywall ``` </TabItem> <TabItem value="Soft/Hard Paywall" label="Zorunlu/İsteğe Bağlı Paywall" default> ```json showLineNumbers { "hard_paywall": true } # By setting it to true, you disalow skipping paywall without subscribing # You have to handle this logic in your app ``` </TabItem> <TabItem value="Translations" label="Çeviriler" default> ```json showLineNumbers { "title": { "en": "Try for free!", "es": "¡Prueba gratis!", "ru": "Попробуй бесплатно!" } } ``` </TabItem> </Tabs> Farklı seçenekleri birleştirebilir ve kendinizinkini oluşturabilirsiniz. Bu sayede farklı başlıkları, metinleri, görselleri, yazı tiplerini, renkleri ve daha fazlasını test edebilirsiniz. ### Remote config'in JSON görünümü \{#json-view-of-the-remote-config\} Remote config'in **JSON** görünümünde istediğiniz JSON formatındaki veriyi girebilirsiniz: <img src="/assets/shared/img/3356ff5-remote_config_JSON.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Remote config'in tablo görünümü \{#table-view-of-the-remote-config\} Kodla çalışmak alışkın olmadığınız bir şeyse ve JSON'daki bazı değerleri düzenlemeniz gerekiyorsa, Adapty'nin **Table** görünümü tam size göre. <img src="/assets/shared/img/4c27b2f-remote_config_table.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> JSON'unuzun okunması ve anlaşılması kolay bir tablo formatındaki kopyasıdır. Renk kodlaması, farklı veri türlerini tanımayı kolaylaştırır. Bir anahtar eklemek için **Add row** düğmesine tıklayın. Değerleri ve tür eşleşmelerini otomatik olarak kontrol eder; düzeltmeleriniz geçersiz bir JSON'a yol açabilecekse sizi uyarırız. <img src="/assets/shared/img/ef682d8-add_raw.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ek satır seçenekleri genellikle [paywall yerelleştirmeleri](add-remote-config-locale) için kullanışlıdır: <img src="/assets/shared/img/17bcf80-remote_config_table_options.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Şimdi [bir placement oluşturma](create-placement) ve paywall'ı ona ekleme zamanı. Bunun ardından, mobil uygulamanızda <InlineTooltip tooltip="remote config paywall'larınızı gösterin">[iOS](present-remote-config-paywalls), [Android](present-remote-config-paywalls-android), [React Native](present-remote-config-paywalls-react-native), [Flutter](present-remote-config-paywalls-flutter) ve [Unity](present-remote-config-paywalls-unity)</InlineTooltip> üzerinde paywall'ları görüntüleyebilirsiniz. --- # File: add-paywall-locale-in-adapty-paywall-builder --- --- title: "Flow Builder'da yerel ayar ekleme" description: "Kullanıcılara kendi dillerinde ulaşmak için Adapty'nin Flow Builder'ında yerelleştirilmiş içerik ekleyin." --- Flow'larınızı yerelleştirmek, bunları birden fazla dilde kullanılabilir hale getirir. Flow Builder'da yerelleştirme ekran bazında düzenlenir; her ekranda çeviri ilerlemenizi takip etmek için bir tamamlanma yüzdesi gösterilir. :::tip Başka diller eklemeden önce flow'unuzu varsayılan yerel ayarda tamamlayın. ::: ## Yerelleştirme ekleme ve ayarlama \{#add-and-set-up-localization\} 1. Sol panelde Localizations simgesine tıklayın. Ardından **Add locale** seçeneğine tıklayın. Eklemek istediğiniz dilleri seçin. 2. Eklenen her yerel ayar, yerelleştirme tablosunda ayrı bir sütun olarak görünür ve varsayılan dil değerleriyle önceden doldurulur. 3. Yalnızca eksik çevirilere odaklanmak için sol paneldeki **Missing only** geçiş düğmesini açın. Tablo, yalnızca çevrilmemiş satırları gösterecek şekilde filtrelenir. ## Harici çeviri için dışa ve içe aktarma \{#export-and-import-for-external-translation\} Çeviri dosyasını çevirmenlerle paylaşmak için dışa aktarabilir, çevrilen sonuçları da içe aktarabilirsiniz. Üst araç çubuğunda **Import / Export** seçeneğine tıklayın. ### Dışa aktarma dosya biçimi \{#export-file-format\} Dışa aktarma işlemi, çevrilebilir her öğe için bir satır içeren `.tsv` (sekmeyle ayrılmış) bir dosya oluşturur. Sütunlar şunlardır: | Sütun | Açıklama | |--------|-------------| | `Screen` | Öğenin ait olduğu ekran (örn. `Welcome`, `Quiz`) | | `Element` | O ekrandaki otomatik oluşturulan öğe tanımlayıcısı. **Interactions** > **Element ID** bölümünden değiştirebilirsiniz. | | `Property` | Özellik türü (örn. `content`) | | `[default_locale]` | Varsayılan dil kodu (örn. `en`) | | `[locale]` | Eklenen her yerel ayar için bir sütun (örn. `fr`, `es`) | Örnek: :::note Çevrilmemiş satırlar için yerel ayar sütunlarını boş bırakın — Adapty bunları eksik olarak değerlendirecektir. ::: ### İçe aktarma dosyası gereksinimleri \{#import-file-requirements\} - **Format**: `.tsv` (sekmeyle ayrılmış değerler) - **Başlıklar**: `Screen`, `Element`, `Property` ve en az bir yerel ayar sütunu içermelidir - **Yerel ayar sütun adları**: flow'a zaten eklenmiş yerel ayar kodlarıyla eşleşmelidir. Flow'da bulunmayan yerel ayar kodları içeren bir dosya içe aktarılırsa hata oluşur. - **Kısmi içe aktarma**: yalnızca belirli satırları ekleyebilirsiniz; dosyada yer almayan satırlar mevcut değerlerini korur ## Manuel olarak çevirin \{#translate-manually\} Ayrıca çevirileri doğrudan yerelleştirme tablosundaki herhangi bir hücreye yazabilirsiniz. Belirli bir satırı yönetmek için bağlam menüsünü açın (**⋮**): - **Reset to default**: Satırın çevirisini varsayılan dil değerlerine geri döndürür. ## Yerelleştirmeyi önizleme \{#preview-the-localization\} Çevirilerinizi kontrol etmek için Flow Builder'da aktif locale'i değiştirin ve her ekranı gözden geçirin. --- # File: add-remote-config-locale --- --- title: "Remote config kullanarak paywallları yerelleştirme" description: "Adapty paywalllarını kişiselleştirmek için remote config lokalleri ekleyin." --- Paywalllarınızı farklı dillere uyarlamak, kültürel çeşitliliğin olduğu günümüz dünyasında büyük önem taşır. Yerelleştirme sayesinde belirli bölgelerdeki kullanıcılar için özelleştirilmiş deneyimler oluşturabilirsiniz. Her paywall için farklı dillerde versiyonlar ekleyerek ürününüzü yerel kitlelere uygun hale getirebilirsiniz. Paywall tasarımında Adapty Paywall Builder kullanmıyorsanız bile özel paywalllarınızı yerelleştirebilir ve uygulamanızı yeniden dağıtmak zorunda kalmadan yerelleştirmeleri yönetebilirsiniz: 1. Adapty kontrol panelinde değişkenler içeren bir remote config oluşturursunuz. Değişkenler metin, medya veya diğer içerik türlerini temsil edebilir. 2. Her lokal için değişken değerlerini ayarlarsınız. 3. Uygulama kodunda değişkenleri işlersiniz. 4. Ürünlerle birlikte bir paywall alıp lokal gönderdiğinizde, doğru değişken değerlerini elde edersiniz. Bu sayede yerelleştirmeler uygulama koduna sabit olarak yazılmaz ve istediğiniz zaman güncelleyebilirsiniz. İster tablo görünümünde ister JSON formatında olsun, her dil için ayarları kolayca yapabilirsiniz. Örneğin string anahtarlarını çevirebilir, Boolean değerleri değiştirebilir (İngilizce için `TRUE`, İtalyanca için `FALSE` gibi) ya da arka plan görsellerini değiştirebilirsiniz. ## Remote config ile yapılandırılmış paywalllar için yerelleştirme kurulumu \{#set-up-localization-for-remote-configured-paywalls\} 1. Adapty'de [**Paywalls**](https://app.adapty.io/paywalls) bölümüne gidin. 2. Açmak istediğiniz paywalla tıklayın. 3. **Remote config** sekmesine geçin. <img src="/assets/shared/img/switch_to_remote_config.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Locales** seçeneğine tıklayın ve desteklemek istediğiniz dilleri seçin. Bu lokalleri paywalla eklemek için değişikliklerinizi kaydedin. <img src="/assets/shared/img/add_locale.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Artık içeriği manuel olarak çevirebilir, yapay zeka kullanabilir ya da harici çevirmenler için yerelleştirme dosyasını dışa aktarabilirsiniz. ## Paywallları yapay zeka ile çevirme \{#translate-paywalls-with-ai\} Yapay zeka destekli çeviri, paywallınızı yerelleştirmenin hızlı ve etkili bir yoludur. Hem **String** hem de **List** değerlerini çevirebilirsiniz. Varsayılan olarak tüm satırlar seçilidir (mor renkte gösterilir). Zaten çevrilmiş satırlar yeşil renkte işaretlenir ve varsayılan olarak yeni çeviriye dahil edilmez. Seçilmemiş veya çevrilmemiş satırlar gri görünür. <img src="/assets/shared/img/localization-table.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/localization-json.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. Çevrilecek satırları seçin. Yapay zekanın bunları çevirmesini önlemek için ID'leri, URL'leri ve değişkenleri içeren satırların seçimini kaldırmanız önerilir. 2. Çeviri yapılacak dilleri seçin. <img src="/assets/shared/img/localization-table-language.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Çevirileri uygulamak için **AI Translate** seçeneğine tıklayın. Seçilen satırlar çevrilecek ve paywalla eklenecek; çevrilen satırlar yeşil olarak işaretlenecektir. ## Harici çeviri için yerelleştirme dosyalarını dışa aktarma \{#exporting-localization-files-for-external-translation\} Yapay zeka destekli yerelleştirme giderek yaygınlaşsa da güçlü bir geçmiş performansa sahip profesyonel insan çevirmenler veya bir çeviri ajansı gibi daha güvenilir yöntemleri tercih edebilirsiniz. Böyle bir durumda yerelleştirme dosyalarını dışa aktarıp çevirmenlerinizle paylaşabilir, ardından çevrilmiş dosyaları Adapty'ye geri aktarabilirsiniz. **Export** düğmesiyle dışa aktarma işlemi, her dil için ayrı `.json` dosyaları oluşturur ve bunları tek bir arşivde paketler. Yalnızca tek bir dosyaya ihtiyacınız varsa, bunu dil bazlı menüden doğrudan dışa aktarabilirsiniz. <img src="/assets/shared/img/localization-single-export.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Çevrilmiş dosyaları aldıktan sonra, hepsini aynı anda veya tek tek yüklemek için **Import** düğmesini kullanın. Adapty, dosyaların doğru formata uygun olduğundan emin olmak için otomatik olarak doğrulama yapacaktır. ### İçe aktarma dosyası formatı \{#import-file-format\} Başarılı bir içe aktarma için dosyanın şu gereksinimleri karşılaması gerekir: - **Dosya Adı ve Uzantısı:** Dosya adı temsil ettiği lokalle eşleşmeli ve `.json` uzantısına sahip olmalıdır. Lokal adını Adapty Kontrol Panelinde doğrulayabilir ve kopyalayabilirsiniz. Ad tanınmazsa içe aktarma başarısız olur. <img src="/assets/shared/img/locale-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Geçerli JSON:** Dosya geçerli bir JSON olmalıdır. Değilse içe aktarma başarısız olur. ## Manuel yerelleştirme \{#manual-localization\} Bazen çevirileri ince ayar yapmak, belirli lokaller için farklı görseller eklemek veya remote config'i doğrudan düzenlemek isteyebilirsiniz. 1. Çevirmek istediğiniz öğeyi seçin ve yeni bir değer girin. Hem **String** hem de **List** değerlerini güncelleyebilir ya da görselleri lokale daha uygun olanlarla değiştirebilirsiniz. <img src="/assets/shared/img/032b429-remote_config_localization.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Yerelleştirme sorunlarını verimli biçimde çözmek için İngilizce lokalindeki bağlam menüsünden yararlanın: - **Copy this value to all locales**: Seçilen satır için İngilizce dışındaki lokallerde yapılmış tüm değişikliklerin üzerine yazar ve İngilizce lokalindeki değerle değiştirir. - **Revert all row changes to original values**: Mevcut oturumda yapılan tüm değişiklikleri iptal eder ve değerleri son kaydedilen durumuna geri yükler. <img src="/assets/shared/img/d7e70f1-remote_confi_loc_table_options.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Paywalla lokaller ekledikten sonra, uygulama kodunuzda lokal kodlarını doğru şekilde kullandığınızdan emin olun. Bkz. <InlineTooltip tooltip="the guides on how to use localizations and locale codes in your app">[iOS](localizations-and-locale-codes), [Android](android-localizations-and-locale-codes)</InlineTooltip> --- # File: web-paywall-configuration --- --- title: "Web paywall yapılandırması" --- **Web paywall** sayfasında **Create web paywall** butonuna tıkladığınızda, web paywall tasarımını ve ödeme yöntemini ayarlamak için ayrı bir sayfaya yönlendirilirsiniz. ## Ödeme yöntemi kurulumu \{#set-up-a-payment-method\} Öncelikle satın almaları yönetecek bir ödeme sağlayıcısı bağlamanız gerekir. Mevcut seçenekler şunlardır: - Stripe - Paddle - Paypal - Solidgate :::important Adapty'de web paywall analizlerinin doğru takip edilebilmesi için ürünlerinizi [Adapty'ye eklerken](product) ilgili Stripe/Paddle/diğer ödeme sağlayıcısı ürün ID'lerini de girmeniz gerekir. ::: Bir ödeme sağlayıcısı kurmak için: 1. Web paywall liste sayfasında **Settings** butonuna tıklayın ve **Integrations** sekmesine geçin. 2. Bir ödeme sağlayıcısı seçin ve ekrandaki entegrasyon talimatlarını izleyin. <img src="/assets/shared/img/web-paywall-configuration-1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ⚠️ Stripe seçerseniz, arayüzde **Sandbox** yazmasına rağmen **Test Mode** ortamına ait anahtarları kullandığınızdan emin olun. Aksi takdirde web paywallınız çalışmaz. Stripe'taki **Sandbox**'lar henüz desteklenmemektedir. <img src="/assets/shared/img/web-paywall-configuration-stripe.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Apple Pay alan adı doğrulamasını kurma \{#set-up-apple-pay-domain-verification\} **Settings > Domains** bölümünde alan adı doğrulaması için kullanmak istediğiniz birincil ödeme sağlayıcısını seçin. Ardından paywall alan adlarınızı ilgili sağlayıcıda doğrulayın: **Stripe**: 1. [Ödeme yöntemi alan adı ayarları](https://dashboard.stripe.com/settings/payment_method_domains) sayfasına gidin ve **Add a new domain** butonuna tıklayın. 2. `app.funnelfox.com` ile kişisel paywall alt alan adınızı (`paywalls-....fnlfx.com` gibi görünür) ekleyin. Alt alan adınızı bulmak için **Settings > Domains** bölümüne gidin ve **Hosted subdomain** değerini kopyalayın. **Paddle**: 1. Paddle konsolunda **Checkout > Website approval** bölümüne gidin ve **Add a new domain** butonuna tıklayın. 2. `app.funnelfox.com` ile kişisel paywall alt alan adınızı (`paywalls-....fnlfx.com` gibi görünür) ekleyin. Alt alan adınızı bulmak için **Settings > Domains** bölümüne gidin ve **Hosted subdomain** değerini kopyalayın. Paddle'da onay süreci manuel yürütüldüğünden, alan adlarının `Pending` durumundan `Approved` durumuna geçmesini beklemeniz gerekir. **FunnelFox Billing**: [FunnelFox Billing entegrasyon talimatlarını](https://funnelfox.com/docs/billing/integration-billing-funnelfox) izleyin. **SolidGate**: 1. Solidgate Kontrol Paneli'nde **Developers > Apple Pay Domains** bölümüne gidin. 2. **+ Add new domain** butonuna tıklayın ve proje alan adınızı (FunnelFox'ta **Settings > Domains** bölümünden) yapıştırın. Varsa özel alan adınızı da ekleyin. 3. Apple Pay'i önizleme modunda kullanmak için `http://app.funnelfox.com/` adresini de ekleyin. ## Web paywall oluşturma ve yapılandırma \{#create-and-configure-a-web-paywall\} 1. Web paywall liste sayfasında **Create a paywall** butonuna tıklayın. 2. Bir paywall adı girin ve **Create** butonuna tıklayın. <img src="/assets/shared/img/web-paywall-configuration-2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. İki abonelik seçeneği ve Apple Pay satın alma butonu içeren temel bir şablona yönlendirileceksiniz. İlk ekranda abonelik planları listelenir. İkinci ve üçüncü ekranlar ödeme ekranlarıdır. Her ekran, sunduğunuz planlardan birine karşılık gelir. Yalnızca bir planınız varsa fazladan ekranı silin; daha fazlası varsa ödeme ekranlarını çoğaltmanız gerekir. Başarılı bir satın almanın ardından kullanıcıların gördüğü son ekranda, uygulamalarına geri dönebileceklerini açıkça belirtmeniz gerekir. <img src="/assets/shared/img/web-paywall-configuration-10.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Plan listesini ayarlayın: plan ve fiyat ekleyin ya da kaldırın. Ekranda gördüğünüz fiyatlar ve planlar dinamik olarak eklenmez, bu nedenle bunları manuel olarak yapılandırmanız gerekir. <img src="/assets/shared/img/web-paywall-configuration-8.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Sahip olduğunuz her plan için bir ödeme ekranı ekleyin veya yapılandırın. Kullanıcıların satın alma butonuna tıklamadan önce ne kadar ödeyeceğini bilmesi için her ödeme ekranına toplam tutar eklemenizi öneririz. 6. Ödeme ekranlarında Apple Pay butonu zaten bulunmaktadır. Butonun çalışması için her ekranda şunları yapılandırın: 1. **Product type**: Deneme süresi mi yoksa indirim mi eklemek istediğinizi seçin. 2. **Trial period**: Deneme süresi uzunluğunu girin. 3. **Product**: Ödeme sağlayıcınızdan ürününüzü seçin. :::important Ürünün Adapty'ye eklendiğinden emin olun. Aksi takdirde satın alma sonucu varsayılan olarak ayarlanır. ::: 4. **Subscription discount**: İsteğe bağlı olarak ödeme sağlayıcınızdan bir kupon seçin. <img src="/assets/shared/img/web-paywall-configuration-6.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Şimdi planları ödeme ekranlarıyla ilişkilendirmeniz gerekir. Plan seçim ekranında **Continue** butonuna tıklayın ve her plan için hedef ekranı seçin. <img src="/assets/shared/img/web-paywall-configuration-9.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Paywall hazır olduğunda, Adapty'de etkinleştirmek için bağlantısını almanız gerekir. Bağlantıyı alma yöntemi, test mi yoksa canlı ortama mı geçeceğinize bağlıdır: 1. **Sandbox testi için**: Sağ üstteki **Preview** butonuna tıklayın ve bağlantıyı kopyalayın. 2. **Canlı ortam için**: Sağ üstteki **Publish** butonuna tıklayın. **Home** butonuna tıklayın ve **URL** sütunundan bağlantıyı kopyalayın. <img src="/assets/shared/img/web-paywall-configuration-11.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Hepsi bu kadar! [Kuruluma devam etmek](web-paywall#step-2-trigger-the-paywall) için bu bağlantıyı kullanın. --- # File: fallback-paywalls --- --- title: "Yedek paywaller" description: "Adapty'de kesintisiz kullanıcı deneyimi sağlamak için yedek paywalleri kullanın." --- Akıcı bir kullanıcı deneyimi sağlamak için [paywallleriniz](paywalls) ve [onboardinglerinizdeki](onboardings) **yedek sürümleri** ayarlamanız önemlidir. Uygulamanız bir paywall yüklediğinde, Adapty SDK sunucularımızdan paywall yapılandırma verilerini ister. Peki ya cihaz, ağ sorunları veya sunucu kesintileri nedeniyle Adapty'ye bağlanamıyorsa? * Kullanıcı daha önce paywall'a eriştiyse ve cihaz verileri önbelleğe aldıysa, uygulama paywall verilerini **önbellekten** yükler. * Cihaz paywall'ı önbelleğe almadıysa, uygulama yerel olarak depolanmış bir yapılandırma dosyası arar. Bu, uygulamanın paywall'ı hatasız görüntülemesine olanak tanır. Adapty, indirip kullanabileceğiniz yedek yapılandırma dosyalarını otomatik olarak oluşturur. Her dosya, *tüm* placementlarınız için platforma özgü yapılandırmalar içerir. ## Başlarken \{#get-started\} 1. Adapty'den [yedek yapılandırma dosyasını indirin](/local-fallback-paywalls). 2. Yedek paywalllerinizi yapılandırmak için Adapty SDK'yı kullanın: * [iOS](ios-use-fallback-paywalls) * [Android](android-use-fallback-paywalls) * [React Native](react-native-use-fallback-paywalls) * [Flutter](flutter-use-fallback-paywalls) * [Unity](unity-use-fallback-paywalls) * [Kotlin Multiplatform](kmp-use-fallback-paywalls) * [Capacitor](capacitor-use-fallback-paywalls) ## Sınırlamalar \{#limitations\} Yedek paywaller sabit kodlanmış ve yerel olarak depolanmıştır; bu nedenle normal Adapty paywalllerinin dinamik özelliklerinden yoksundur. * Yedek paywaller [uluslararasılaştırmayı](paywall-localization) desteklemez. Adapty yapılandırma dosyasını oluştururken varsayılan `en` yerel ayarını kullanır. * Her placement için yalnızca bir yedek paywall olabilir. Kurulumunuz farklı [kitleler](audience) için farklı paywall yapılandırmaları içeriyorsa, Adapty "Tüm kullanıcılar" için tasarlanan yapılandırmayı kullanır. * Yedek paywaller [A/B testini](ab-tests) desteklemez. Bir paywall A/B testine katılıyorsa, yedek yapılandırma dosyası en yüksek ağırlığa sahip varyantı içerecektir. * Yedek paywaller [uzaktan yönetilemez](customize-paywall-with-remote-config). Yapılandırma dosyasını güncellemek istiyorsanız App Store / Google Play'de uygulamanın yeni bir sürümünü yayımlamanız gerekir. --- # File: local-fallback-paywalls --- --- title: "Yedek paywallları indirin" description: "Sorunsuz abonelik akışları sağlamak için Adapty'de yerel yedek paywallları kullanın." --- Adapty, [yedek paywalllarınız](/fallback-paywalls) için her platform başına birer tane olmak üzere otomatik olarak JSON yapılandırma dosyaları oluşturur. Bu dosyalar aynı zamanda onboardinglarınız için de yedek verileri içerir. Tek bir placement'ta birden fazla paywall veya onboarding bulunuyorsa, yedek sürüm en yüksek ağırlığa ya da en geniş kitleye sahip varyantı içerecektir. Adapty, paywalllarınızı veya onboardinglarınızı her güncellediğinizde bu dosyaları da günceller. Yedek yapılandırmalarınızı indirmek için aşağıdaki adımları izleyin: 1. **[Placements](https://app.adapty.io/placements)** sayfasını açın. 2. **Fallbacks** düğmesine tıklayın. 3. Açılır menüden hedef platformunuzu (*iOS* veya *Android*) seçin. 4. İndirmeyi başlatmak için SDK sürümünüzü seçin. <img src="/assets/shared/img/9c63367-placements.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## İndirdikten sonra \{#after-the-download\} Kullandığınız platforma ait kurulum kılavuzunu takip edin: * [iOS](ios-use-fallback-paywalls) * [Android](android-use-fallback-paywalls) * [React Native](react-native-use-fallback-paywalls) * [Flutter](flutter-use-fallback-paywalls) * [Unity](unity-use-fallback-paywalls) * [Kotlin Multiplatform](kmp-use-fallback-paywalls) * [Capacitor](capacitor-use-fallback-paywalls) --- # File: paywall-metrics --- --- title: "Paywall metrikleri" description: "Abonelik gelirini artırmak için paywall performans metriklerini takip edin ve analiz edin." --- Adapty, paywall'larınızın performansını daha iyi ölçmenize yardımcı olmak için bir dizi metrik toplar. Görüntüleme sayısı birkaç dakikada bir güncellenirken, diğer tüm metrikler gerçek zamanlı olarak güncellenir. Görüntüleme sayısı dışındaki tüm metrikler, paywall içindeki ürüne atfedilir. Bu belge, mevcut metrikleri, tanımlarını ve nasıl hesaplandıklarını açıklamaktadır. Paywall metrikleri, paywall listesinde görüntülenerek tüm paywalllarınızın performansına genel bir bakış sunar. Bu birleşik görünüm, her paywall için toplanmış metrikleri bir arada gösterir; böylece etkinliklerini değerlendirip iyileştirme alanlarını kolayca belirleyebilirsiniz. Her paywall'ı daha ayrıntılı analiz etmek için paywall detay metriklerine gidebilirsiniz. Bu bölümde, seçilen paywalla özgü kapsamlı metrikler yer alır ve performansı hakkında daha derin içgörüler sunar. ### Metrikleri kurulum tarihine göre filtrele \{#filter-metrics-by-install-date\} Paywall, deneme süresi ve satın alma metrikleri iki farklı tarihe göre gruplandırılabilir: - **Etkinlik tarihi** — paywall'ın görüntülendiği, deneme süresinin başladığı veya satın almanın gerçekleştiği tarih. - **Yükleme tarihi** — kullanıcının uygulamayı ilk kez açtığı tarih. Aynı tarih aralığı için bu iki görünüm çok farklı sayılar gösterebilir. **Filter metrics by install date** onay kutusu, kontrol panelinin hangisini kullanacağını belirler: - **İşaretsiz (varsayılan)**: Metrikler etkinlik tarihine göre gruplandırılır. - **İşaretli**: Metrikler yükleme tarihine göre gruplandırılır. **Örnek.** Tarih aralığını 1–30 Nisan olarak ayarlayıp deneme sürelerine bakıyorsunuz. - **İşaretsiz**: O kullanıcıların uygulamayı ne zaman yüklediğinden bağımsız olarak Nisan'da *başlayan* deneme sürelerini gösterir. - **İşaretli**: Deneme sürelerinin ne zaman başladığından bağımsız olarak Nisan'da *yükleme yapan* kullanıcıların deneme sürelerini gösterir. Belirli bir kohort için kullanıcı edinme performansını ölçmek istiyorsanız yükleme tarihi görünümünü kullanın. Belirli bir dönemdeki paywall veya onboarding etkinliğini ölçmek içinse etkinlik tarihi görünümünü tercih edin. ### Metrik kontrolleri \{#metrics-controls\} Sistem, metrikleri seçilen zaman dilimine göre gösterir ve üç düzeyli girinti kullanarak sol sütundaki parametreye göre düzenler. Aktif paywall'lar için metrikler, paywall'ın başlangıç tarihinden günümüze kadar olan dönemi kapsar. Aktif olmayan paywall'lar için ise metrikler, başlangıç tarihinden seçilen zaman diliminin sonuna kadar olan tüm dönemi kapsar. Taslak ve arşivlenmiş paywall'lar metrik tablosuna dahil edilir; ancak bu paywall'lara ait veri yoksa yalnızca listelenir, herhangi bir metrik gösterilmez. #### Metrik verileri için görüntüleme seçenekleri \{#view-options-for-metrics-data\} Paywall sayfası, metrik verileri için iki görüntüleme seçeneği sunar: placement bazlı ve kitle bazlı. Placement bazlı görünümde, metrikler paywall ile ilişkili placement'lara göre gruplandırılır. Bu sayede kullanıcılar, metrikleri farklı placement'lara göre analiz edebilir. Kitle tabanlı görünümde metrikler, paywall'ın hedef kitlesine göre gruplandırılır. Kullanıcılar, farklı kitle segmentlerine özgü metrikleri inceleyebilir. Paywall detay sayfasının üst kısmındaki açılır menüden tercih ettiğiniz görünümü seçebilirsiniz. #### Zaman aralıkları \{#time-ranges\} Metrik verilerini analiz etmek için çeşitli zaman dilimleri arasından seçim yapabilirsiniz; böylece günler, haftalar, aylar veya özel tarih aralıkları gibi belirli sürelere odaklanabilirsiniz. #### Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: Adapty, metrik analizini ihtiyaçlarınıza göre filtrelemenizi ve özelleştirmenizi sağlayan güçlü araçlar sunar. Adapty'nin metrik sayfasıyla çeşitli zaman aralıklarına, gruplama seçeneklerine ve filtreleme olanaklarına erişebilirsiniz. - Filtrele: Kitle, ülke, paywall, paywall durumu, paywall grubu, placement, ülke, mağaza, ürün ve ürün mağazasına göre. - Grupla: Ürün ve mağazaya göre. #### Tekil metrik grafiği \{#single-metrics-chart\} Paywall metrik sayfasının temel bileşenlerinden biri, seçilen metrikleri görsel olarak sunan ve analizi kolaylaştıran grafik bölümüdür. Paywall metrik sayfasındaki grafik bölümü, seçilen metrik değerlerini görsel olarak temsil eden yatay bir çubuk grafik içerir. Grafikteki her çubuk bir metrik değerine karşılık gelir ve boyutu orantılı olduğundan verileri bir bakışta anlamak kolaylaşır. Yatay çizgi analiz edilen zaman dilimini, dikey sütun ise metriklerin sayısal değerlerini gösterir. Tüm metrik değerlerinin toplamı grafiğin yanında görüntülenir. Ayrıca, grafik bölümünün sağ üst köşesindeki ok simgesine tıklandığında görünüm genişler ve seçilen metrikler grafiğin tamamında gösterilir. #### Toplam metrik özeti \{#total-metrics-summary\} Tekli metrik grafiğinin yanında, toplam metrik özeti bölümü yer alır. Bu bölüm, seçilen metriklerin belirli bir zaman noktasındaki kümülatif değerlerini gösterir; açılır menü aracılığıyla görüntülenen metriği değiştirebilirsiniz. ### Metrik Tanımları \{#metrics-definitions\} :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: #### Gelir \{#revenue\} Bu metrik, satın almalar ve yenilemelerden USD cinsinden elde edilen toplam para miktarını gösterir. Gelir hesaplamasının App Store / Play Store komisyonunu içermediğini ve herhangi bir ücret düşülmeden önce hesaplandığını lütfen unutmayın. #### Kazanç \{#proceeds\} Bu metrik, uygulanabilir App Store / Play Store komisyonu düşüldükten sonra uygulama sahibinin satın almalar ve yenilemelerden USD cinsinden aldığı gerçek para miktarını gösterir. :::important Uygulamanız indirimli komisyon programına kayıtlıysa Adapty'yi bilgilendirin. Doğru hesaplamalar için [Small Business Program](app-store-small-business-program) ve [Reduced Service Fee program](google-reduced-service-fee) durumunuzu [uygulama ayarlarınızda](general) belirtin. ::: Uygulamanın kazancına doğrudan katkıda bulunan net geliri yansıtır. Gelirlerin nasıl hesaplandığı hakkında daha fazla bilgi için Adapty [belgelerine](analytics-cohorts#revenue-vs-proceeds) başvurabilirsiniz. #### ARPPU \{#arppu\} ARPPU, ödeme yapan kullanıcı başına ortalama gelir demektir. Toplam gelirin benzersiz ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. 15.000 $ gelir / 1.000 ödeme yapan kullanıcı = 15 $ ARPPU. #### ARPAS \{#arpas\} Aktif abone başına ortalama gelir (ARPAS), her aktif abone için üretilen ortalama geliri ölçmenizi sağlar. Toplam gelirin, deneme sürümü veya abonelik başlatan abone sayısına bölünmesiyle hesaplanır. Örneğin toplam gelir 5.000 $ ve 1.000 abone varsa ARPAS 5 $ olur. Bu metrik, abone başına ortalama para kazanma potansiyelini değerlendirmeye yardımcı olur. #### Satın almalara göre benzersiz dönüşüm oranı (CR) \{#unique-conversion-rate-cr-to-purchases\} Satın almalara göre benzersiz dönüşüm oranı, satın alma sayısının benzersiz görüntülenme sayısına bölünmesiyle hesaplanır. Örneğin, 10 satın alma ve 100 benzersiz görüntülenme varsa, satın almalara göre benzersiz dönüşüm oranı %10 olur. Bu metrik, satın almaların benzersiz görüntülenme sayısına oranına odaklanarak benzersiz ziyaretçileri ödeme yapan müşterilere dönüştürmedeki etkinliğe dair bilgiler sunar. #### Satın almalara göre CR \{#cr-to-purchases\} Satın alımlara dönüşüm oranı, satın alım sayısının toplam görüntüleme sayısına bölünmesiyle hesaplanır. Örneğin, 10 satın alım ve 100 görüntüleme varsa satın alımlara dönüşüm oranı %10 olur. Bu metrik, görüntülemelerin yüzde kaçının satın alımla sonuçlandığını gösterir ve paywall'ınızın kullanıcıları ödeme yapan müşterilere dönüştürme etkinliği hakkında içgörü sunar. #### Deneme sürümlerine benzersiz CR \{#unique-cr-to-trials\} Deneme sürümlerine benzersiz dönüşüm oranı, başlatılan deneme sayısının benzersiz görüntüleme sayısına bölünmesiyle hesaplanır. Örneğin, 30 deneme başlatma ve 100 benzersiz görüntüleme varsa deneme sürümlerine benzersiz dönüşüm oranı %30 olur. Bu metrik, benzersiz görüntülemelerin yüzde kaçının deneme aktivasyonuyla sonuçlandığını ölçer ve paywall'ınızın benzersiz ziyaretçileri deneme kullanıcılarına dönüştürme etkinliği hakkında içgörü sunar. #### Satın alımlar \{#purchases\} Satın alımlar, paywall üzerinde gerçekleştirilen çeşitli işlemlerin kümülatif toplamını temsil eder. Bu metriğe aşağıdaki işlemler dahildir (yenilemeler dahil değildir): - Doğrudan paywall üzerinde yapılan yeni satın alımlar. - Başlangıçta paywall üzerinde başlatılan denemelerin aboneliğe dönüşümleri. - Paywall üzerinde yapılan abonelik düşürme, yükseltme ve çapraz geçişler. - Otomatik yenileme olmadan sona ermenin ardından aboneliğin yeniden başlatılması gibi paywall üzerindeki abonelik geri yüklemeleri. Bu farklı işlem türlerini göz önünde bulundurarak satın alımlar metriği, paywall'ınızdaki genel edinim ve monetizasyon faaliyetlerine kapsamlı bir bakış sunar. #### Denemeler \{#trials\} Denemeler metriği, aktive edilen toplam deneme sayısını temsil eder. Paywall'ınız aracılığıyla deneme süresi başlatan kullanıcı sayısını yansıtır. Bu metrik, deneme teklifinizin etkinliğini takip etmeye yardımcı olur ve kullanıcı etkileşimi ile denemelerden ücretli aboneliklere dönüşüm hakkında içgörü sağlayabilir. #### İptal edilen denemeler \{#trials-canceled\} İptal edilen denemeler metriği, otomatik yenileme özelliğinin kapatıldığı deneme sayısını temsil eder. Bu durum, kullanıcıların denemeden manuel olarak çıkış yapmasıyla gerçekleşir ve deneme süresi sona erdikten sonra aboneliğe devam etmeme kararını gösterir. İptal edilen denemelerin takibi, kullanıcı davranışı hakkında değerli bilgiler sağlar ve kullanıcıların denemeden çıkış oranını anlamanıza olanak tanır. #### İadeler \{#refunds\} İadeler metriği, iade edilen satın alma ve aboneliklerin sayısını temsil eder. Bu; müşteri talepleri, ödeme sorunları veya geçerli iade politikaları gibi çeşitli nedenlerle geri alınan ya da iade edilen işlemleri kapsar. #### İade oranı \{#refund-rate\} İade oranı, iade sayısının ilk kez yapılan satın alma sayısına bölünmesiyle hesaplanır (yenilemeler dahil değildir). Örneğin, 5 iade ve 1000 ilk kez yapılan satın alma varsa, iade oranı %0,5 olur. #### Görüntülemeler \{#views\} Görüntülemeler metriği, paywall'ın kullanıcılar tarafından toplam kaç kez görüntülendiğini temsil eder. Bir kullanıcı paywall'ı her ziyaret ettiğinde ayrı bir görüntüleme olarak sayılır. Örneğin, bir kullanıcı paywall'ı iki kez ziyaret ederse bu iki görüntüleme olarak kaydedilir. Görüntülemelerin takibi, paywall'ınızdaki etkileşim ve kullanıcı etkileşimi düzeyini anlamanıza, kullanıcı davranışı ve paywall yerleşiminizin ile tasarımınızın etkinliği hakkında içgörü edinmenize yardımcı olur. #### Benzersiz görüntülemeler \{#unique-views\} Benzersiz görüntülemeler metriği, paywall'ın kullanıcılar tarafından kaç kez benzersiz olarak görüntülendiğini temsil eder. Her ziyareti ayrı bir görüntüleme olarak sayan toplam görüntülemelerin aksine, benzersiz görüntülemeler her kullanıcının paywall'a erişimini kaç kez gerçekleştirdiğinden bağımsız olarak yalnızca bir kez sayar. Örneğin, bir kullanıcı paywall'ı iki kez ziyaret ederse bu bir benzersiz görüntüleme olarak kaydedilir. Benzersiz görüntülemelerin takibi, toplam ziyaret sayısı yerine bireysel kullanıcılara odaklandığından kullanıcı etkileşiminin ve paywall'ınızın erişiminin daha doğru bir ölçüsünü sağlar. :::warning Paywall görüntülemelerini `.logShowFlow()` (iOS SDK v4+) / `.logShowPaywall()` metodunu kullanarak Adapty'ye gönderdiğinizden emin olun. Aksi takdirde, paywall görüntülemeleri metriklere yansımaz ve dönüşüm verileri anlamsız hale gelir. ::: --- # File: migrate-paywalls --- --- title: "Paywallları uygulamalar arasında taşıma" description: "Adapty'de paywallları diğer uygulamalardan nasıl taşıyacağınızı öğrenin." --- Adapty ile her uygulama için sıfırdan paywall oluşturmanıza gerek yok. Birden fazla uygulama yönetiyorsanız, builder ile oluşturulmuş herhangi bir paywall'ın Paywall Builder yapılandırmasını bir uygulamadan diğerine taşıyabilirsiniz. Taşıma işlemi tüm görsel yapılandırmaları kopyalar: - Paywall ve tüm paywall öğeleri için düzen ayarları - Medya - Yerelleştirme Taşıma yalnızca builder yapılandırması için geçerlidir; ürünleri veya remote config'i kopyalamaz. :::note Özel fontlar içeren bir Paywall Builder yapılandırmasını taşırsanız, fontlar hatalı görüntülenebileceğinden bunları bir cihazda test edin. ::: ## Paywall taşıma \{#migrate-paywall\} :::important Yalnızca **yeni** Adapty Paywall Builder'da oluşturulan paywallları taşıyabilirsiniz. **Eski** Paywall Builder ile oluşturulan paywallları taşımak için önce bunları yeni Paywall Builder'a geçirmeniz gerekir. ::: Bir Paywall Builder yapılandırmasını taşımak için: 1. **Yeni paywall için**: [Paywall oluşturma](create-paywall) adımlarını başlatın ve ürünleri ekleyin. Ardından şablon kitaplığını açmak için **Build no-code paywall** seçeneğine tıklayın. **Mevcut paywall için**: **Builder & Generator** sekmesindeki **Layout settings** bölümüne gidin ve **Change template** seçeneğine tıklayın. 2. Paywall şablonunu düzenlerken **Copy a design from your apps** kutusunun içindeki **Choose paywall** seçeneğine tıklayın. <img src="/assets/shared/img/migrate-paywall-builder.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Yapılandırmayı kopyalamak istediğiniz uygulamayı ve paywall'ı seçin. <img src="/assets/shared/img/migrate-app.png" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Copy Selected Paywall** seçeneğine tıklayın. Taşıma işleminin ardından istediğiniz düzenlemeleri yapabilirsiniz; bu değişiklikler orijinal paywall'ı etkilemez. --- # File: duplicate-paywalls --- --- title: "Paywall'ı kopyalama" description: "Adapty'de kopyalanmış paywall'ları nasıl yöneteceğinizi ve paywall performansını nasıl optimize edeceğinizi öğrenin." --- Adapty'deki mevcut bir paywall'da küçük değişiklikler yapmanız gerekiyorsa, özellikle bu paywall zaten mobil uygulamanızda kullanılıyorsa ve analizlerinizi bozmak istemiyorsanız, paywall'ı kolayca kopyalayabilirsiniz. Bu kopyaları, gerektiğinde bazı veya tüm placement'larda orijinal paywall'ların yerine kullanabilirsiniz. Bu işlem, paywall'ın adı, ürünleri ve promosyonları gibi tüm ayrıntılarıyla birlikte bir kopyasını oluşturur. Yeni paywall'ın adına "Copy" eklenerek orijinalden kolayca ayırt edilmesi sağlanır. Adapty kontrol panelinde bir paywall'ı kopyalamak için: 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümünü açın. Adapty kontrol panelindeki paywall listesi sayfası, hesabınızdaki tüm paywall'lara genel bir bakış sunar. 2. Paywall'ın yanındaki **3 nokta** düğmesine tıklayın ve **Duplicate** seçeneğini seçin. <img src="/assets/shared/img/duplicate.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Yeni paywall'ı düzenleyin ve **Save** düğmesine tıklayın. 4. Orijinal paywall herhangi bir placement'ta kullanılıyorsa Adapty, orijinal paywall'ların placement'larda kopyalarıyla değiştirilmesi için sizi yönlendirecektir. **Create and replace original** seçeneğini seçerseniz yeni paywall'lar hemen **Live** durumuna geçer. Alternatif olarak, bunları **Draft** durumunda yeni paywall'lar olarak oluşturup daha sonra placement'lara ekleyebilirsiniz. --- # File: archive-paywalls --- --- title: "Paywallı arşivle" description: "Adapty'de eski paywallları veri kaybetmeden nasıl arşivleyeceğinizi öğrenin." --- Adapty'yi kullanmaya başladıkça ve paywall ayarlarınızı ince ayarladıkça, artık mevcut stratejinize veya kampanyalarınıza uymayan paywalllar birikebilir. `Inactive` (Pasif) olarak bırakılan bu kullanılmayan paywalllar çalışma alanınızı karmaşık hale getirerek en önemli olanları bulmayı zorlaştırabilir. Bunu çözmek için Adapty, gereksiz paywallları arşivleme seçeneği sunuyor. Arşivleme, bu paywallların kalıcı olarak silinmeden güvenli bir şekilde saklanmasını sağlar; gerektiğinde gelecekte erişilebilir olacak şekilde hazır tutulur. Ayrıca arşivlenen paywalllar varsayılan görünümden filtrelenebilir, böylece çalışma alanınız sadeleşir ve kullanıcı arayüzünüz daha anlaşılır hale gelir. Bu kılavuzda, Adapty'de paywallları verimli şekilde arşivleme adımlarını ele alacağız; böylece paywall yönetim süreciniz üzerinde daha fazla kontrol sahibi olacaksınız. Küçük bir hatırlatma: En az bir placement'ta aktif olarak kullanılan canlı paywalllar arşivlenemez. Böyle bir paywallı arşivlemek istiyorsanız önce tüm placement'lardan kaldırmanız yeterlidir. :::note Arşivlenmemiş bir A/B testinde kullanılan bir paywallı arşivleyemezsiniz. Bu sayede kullanıcı, tamamlanan bir A/B testinin ayrıntılı metriklerini görüntüleyebilir ve bağlantılı paywall bu verilerin bir parçasıdır. ::: **Bir paywallı arşivlemek için:** 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümünü açın. 2. Paywallın yanındaki **3-nokta** düğmesine tıklayın ve **Archive** seçeneğini seçin. <img src="/assets/shared/img/archive-paywall.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Archive paywall** penceresindeyken arşivlemek istediğiniz paywallın adını yazın ve ardından **Archive** düğmesine tıklayın. --- # File: restore-paywall --- --- title: "Paywall'ı arşivden geri getirme" description: "Kullanıcılara kesintisiz abonelik hizmeti sunmak için Adapty'deki paywall'ları geri yükleyin." --- Paywall'ları arşivleyebilmek, paywall yönetim sürecinizi kolaylaştıran çok işlevli bir özelliktir. Artık ihtiyaç duyulmayan paywall'ları gizleyerek çalışma alanınızı daha düzenli tutmanızı sağlar. Üstelik arşivlenmiş paywall'ları geri yükleyebilme seçeneği, gerektiğinde bunları stratejinize yeniden dahil etme esnekliği sunar. Arşivlenmiş paywall'lar varsayılan görünümde filtrelenmiş olabilir. Bunları görmek için **State** filtresinde **Archived** seçeneğini seçin. **Bir paywall'ı arşivden geri getirmek için** 1. Adapty ana menüsünde [**Paywalls**](https://app.adapty.io/paywalls) bölümünü açın. 2. Arşivlenmiş paywall'ların listede görüntülendiğinden emin olun. Görüntülenmiyorsa sağ taraftaki filtreyi güncelleyin. <img src="/assets/shared/img/paywall-filter.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Arşivlenmiş paywall'ın yanındaki **3 nokta** düğmesine tıklayın ve **Back to active** seçeneğini seçin. <img src="/assets/shared/img/restore-paywall.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: profiles-crm --- --- title: "Profiller/CRM" description: "Kitle segmentasyonunu geliştirmek için Adapty'de kullanıcı profillerini ve CRM verilerini yönetin." --- Profiller, kullanıcılarınız için bir CRM'dir. Profiller ile şunları yapabilirsiniz: 1. Profil ID, müşteri kullanıcı ID'si, e-posta veya işlem ID'si ile belirli kullanıcıları bulun. 2. Faturalama sorunları, ek süre ve diğer [olaylar](events) dahil olmak üzere kullanıcının olay zaman çizelgesini görüntüleyin. 3. Abonelik durumu, toplam gelir/kazanç ve daha fazlası gibi kullanıcı özelliklerini analiz edin. 4. Kullanıcıya abonelik verin. :::note Etkinlik akışındaki olaylar kontrol paneline gecikmeli olarak ulaşır. Yeni profiller ve özellik değişiklikleri hemen görünmeyebilir. ::: <img src="/assets/shared/img/profiles.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::link Adapty'nin kullanıcı profillerini nasıl oluşturduğunu ve bağladığını anlamak için bkz. [Profiller nasıl çalışır](how-profiles-work). ::: ## Kullanıcıları bulma \{#finding-users\} Profiller listesinde belirli bir kullanıcıyı şu yöntemlerle arayabilirsiniz: - **Profile ID**: Adapty'nin kullanıcı için dahili tanımlayıcısı (Adapty ID olarak da bilinir). - **Customer user ID**: Uygulamanızın kullanıcı için tanımlayıcısı (eğer ayarladıysanız). - **Email**: Özel attribute olarak gönderildiyse kullanıcının e-posta adresi. - **Transaction ID**: Bir satın alma işleminden elde edilen mağaza işlem kimliği. Kullanıcının tam profilini açmak için herhangi bir satıra tıklayın. ## Abonelik durumu \{#subscription-state\} Profiller listesinde, kullanıcıları abonelik durumuna göre filtreleyebilir ve sıralayabilirsiniz. Durum değerleri şunlardır: | Kullanıcı **durumu** | Açıklama | | :--------------------- | :----------------------------------------------------------- | | Subscribed | Kullanıcının otomatik yenileme etkin şekilde aktif bir aboneliği var. | | Auto-renew off | Kullanıcı otomatik yenilemeyi kapattı ancak abonelik süresi dolana kadar premium özelliklere erişimi devam ediyor. | | Subscription cancelled | Kullanıcı aboneliğini iptal etti ve abonelik tamamen sona erdi. | | Billing issue | Abonelik veya deneme süresi dolduktan sonra ödeme alınamadı. | | Grace period | Abonelik veya deneme süresi dolduğunda ödeme alınamadığı için kullanıcı şu anda ek süre içinde. | | Active trial | Kullanıcının şu anda deneme sürecinde olan aktif bir aboneliği var. | | Trial cancelled | Kullanıcı deneme süresini iptal etti ve aktif bir aboneliği yok. | | Never subscribed | Kullanıcı hiç abonelik başlatmadı veya deneme süresine girmedi; ücretsiz kullanıcı olarak kalmaya devam ediyor. | ## Kullanıcı nitelikleri \{#user-attributes\} <img src="/assets/shared/img/ce8df4d-CleanShot_2023-06-26_at_20.32.232x.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> SDK aracılığıyla Adapty'ye ek kullanıcı özellikleri gönderebilirsiniz. Adapty varsayılan olarak şunları ayarlar: | Özellik | Açıklama | | ---------------- | ------------------------------------------------------------ | | Customer user ID | Son kullanıcınızın sisteminizdeki tanımlayıcısı. | | Adapty ID | Son kullanıcınızın Adapty içindeki dahili tanımlayıcısı; Profile ID olarak da adlandırılır. | | IDFA | Apple'ın bir kullanıcının cihazına atadığı Reklamverenler için Tanımlayıcı. iOS 14 ve sonrasında App Tracking Transparency (ATT) izni gerektirir. Android'de kullanılamaz. | | Country | Son kullanıcınızın ülkesi. | | OS | Son kullanıcının kullandığı işletim sistemi. | | Device | Son kullanıcıya görünen cihaz model adı. | | Install date | Kullanıcının Adapty'de ilk kez kaydedildiği tarih: <ul><li>Kullanıcının oluşturulduğu tarih. </li><li>Kullanıcı Adapty'yi entegre etmeden önce uygulamanızı yüklediyse, yükleme tarihi ilk işlemin gerçekleştiği tarihi yansıtır.</li><li>Geçerli olduğu durumlarda, geçmiş veri aktarımı sırasında sağlanan tarih.</li></ul> | | Created at | Kullanıcının oluşturulduğu tarih. | En azından dahili kullanıcı kimliğinizi veya kullanıcı e-postanızı gönderin. Bu, kullanıcıları Profiller listesinde bu tanımlayıcılarla bulmanızı sağlar. SDK'yı yükledikten sonra Adapty, ödeme kuyruğundaki kullanıcı olaylarını otomatik olarak toplar ve bunları kullanıcı profilinde görüntüler. Yukarıdaki tablodaki özellikler otomatik olarak toplanır — bunları manuel olarak göndermenize gerek yoktur. ### Özel nitelikler \{#custom-attributes\} Bir profilin **Attributes** bölümünde, SDK veya API aracılığıyla ayarlanan özel nitelikleri görebilirsiniz. Ayrıca **Add attribute** düğmesini kullanarak nitelikleri manuel olarak da atayabilirsiniz. <img src="/assets/shared/img/378c1fb-add_attribute.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ## Abonelik verme \{#granting-a-subscription\} Bir profilde, kullanıcının satın alma yapmasına gerek kalmadan aktif bir aboneliği uzatabilir ya da kullanıcıya bir access level için süresiz erişim verebilirsiniz. <img src="/assets/shared/img/b1d74fd-edit_paid_access_level.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> Bu özellik en çok şu durumlarda işe yarar: - Fatura veya destek sorunu yaşayan bir kullanıcıyı tazmin etmek. - Manuel promosyon veya beta programları yürütmek. - Gerçek bir satın alma yapmadan abonelik flow'larını test etmek. Erişim vermek için kullanıcının profilini açın, **Access levels** bölümüne gidin ve **Edit**'e tıklayın. Son kullanma tarihini ayarlayıp kaydedin. Son kullanma tarihi gelecekte olmalı ve bir kez ayarlandıktan sonra azaltılamaz. Aktif abonelikler için yapılan değişiklikler devam eden ödemeleri etkilemez. :::note Erişim vermek App Store veya Google Play satın alma olayı oluşturmaz. Kullanıcının etkinlik akışı ve analizleri gerçek bir satın alma flow'undan farklı olacaktır. ::: Erişimi programatik olarak da verebilirsiniz; bunun için [Grant access level](api-adapty/operations/grantAccessLevel) API metodunu kullanın. ## Kullanıcı hesapları arasında ücretli erişimi paylaşma \{#sharing-paid-access-between-user-accounts\} :::link Ana makale: [Kullanıcı hesapları arasında ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ::: ### Access paylaşım geçmişi \{#access-sharing-history\} Access level'lar paylaşıldığında veya aktarıldığında, kullanıcının profili bağlı profile — erişimi paylaşan veya erişimi alan profile — bir bağlantı gösterir. Bağlı profili görüntülemek için kullanıcının **Profile** sayfasında access level'ın yanındaki bağlantıya tıklayın. <img src="/assets/shared/img/profile-access-level-origin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Sanal para birimi bakiyeleri, access level'lar gibi profiller arasında paylaşılmaz veya aktarılmaz. Her bakiye tek bir profilde kalır — bkz. [Bakiyeler, profiller ve cihazlar](virtual-currency-balance#balances-profiles-and-devices). ::: ## Sonraki adımlar \{#next-steps\} - Adapty'nin profilleri nasıl oluşturup bağladığını anlamak için bkz. [Profiller nasıl çalışır](how-profiles-work). - Erişim paylaşım politikasını yapılandırmak için bkz. [Kullanıcı hesapları arasında ücretli erişim paylaşımı](sharing-paid-access-between-user-accounts). - Erişimi programatik olarak vermek için bkz. [Access level ver](api-adapty/operations/grantAccessLevel) API yöntemi. --- # File: how-profiles-work --- --- title: "Profiller nasıl çalışır" description: "Adapty'nin kullanıcı profillerini nasıl oluşturduğunu, takip ettiğini ve bağladığını anlayın — anonim profiller, kimliği belirlenmiş kullanıcılar ve ebeveyn/kalıtımcı ilişkileri dahil." --- Uygulamanızdaki her kullanıcı, satın alımlarını, olaylarını ve abonelik durumunu takip eden bir Adapty profiline sahip olur. Profillerin nasıl oluşturulduğunu ve birbirine bağlandığını anlamak; entegrasyon hatalarını önlemenize, veri parçalanmasını engellemenize ve [Profiller](profiles-crm) bölümündeki verileri doğru yorumlamanıza yardımcı olur. ## Profil oluşturma \{#profile-creation\} Adapty, bir kullanıcı uygulamanızı ilk kez açtığında otomatik olarak bir profil oluşturur. **Customer User ID olmadan** profil anonimdir. Her şu durumda yeni bir anonim profil oluşturulur: - Kullanıcı uygulamayı yeniden yüklediğinde - Kullanıcı uygulamanızdan çıkış yaptığında (uygulamanız `Adapty.logout()` çağırdığında) Satın alımlar, kalıcı bir kullanıcı kimliğine değil, uygulama kurulumuna bağlıdır. **Customer User ID ile** profil, yeniden yüklemeler ve cihazlar arasında kalıcı olur. Customer user ID kullanmak şunları sağlar: 1. Kullanıcıyı uygulama yeniden yüklemeleri ve birden fazla cihaz üzerinden takip edebilirsiniz. 2. Kullanıcıları [**Profiles**](profiles-crm) bölümünde customer user ID'lerine göre bulabilirsiniz. 3. Customer user ID'yi [sunucu tarafı API](getting-started-with-server-side-api)'sinde kullanabilirsiniz. 4. Adapty, customer user ID'yi tüm entegrasyonlara gönderir. Customer user ID ile profil davranışı, bunu ne zaman ayarladığınıza bağlıdır: - **SDK etkinleştirmesinde**: Adapty, o customer user ID'ye sahip mevcut profili kullanır (geri dönen kullanıcılar için) veya yeni bir profil oluşturur (ilk kez gelen kullanıcılar için). - **SDK etkinleştirmesinden sonra**: Adapty, etkinleştirmede anonim bir profil oluşturur. Kullanıcıyı daha sonra tanımladığınızda Adapty, customer user ID'yi anonim profile bağlar (ilk kez gelen kullanıcılar için) veya o ID'ye sahip mevcut profile geçer (geri dönen kullanıcılar için). **Hangi yaklaşımı kullanmalısınız:** - **Uygulama başlangıcında customer user ID mevcutsa** (örneğin, önceki bir oturumdan kaydedilmişse) — SDK'yı başlatırken `activate()` fonksiyonuna iletin. - **Kullanıcılar uygulama başladıktan sonra giriş yapıyorsa** — kimlik doğrulamanın ardından `identify()` fonksiyonunu çağırın. Adapty, ID'yi mevcut profile bağlar (ID yeniyse) veya mevcut profile geçer (ID zaten varsa). - **Kullanıcılar giriş yapmadan önce satın alım yapabiliyorsa** — girişin ardından `identify()` fonksiyonunu çağırın. Customer user ID Adapty'de zaten mevcutsa, mevcut access level'ı senkronize etmek için ardından profili alın. Uygulama ayrıntıları için [kullanıcıları tanımlama](identifying-users) SDK kılavuzuna bakın. :::note Geri dönen bir kullanıcı daha önce uygulamanızı customer user ID olmadan kullandıysa, SDK etkinleştirmesinde tanımlamaya başladığınızda bu anonim profiller otomatik olarak birleştirilmez. Bu tür kullanıcılar için eksiksiz geçmişi korumak amacıyla bunun yerine girişten sonra `identify()` kullanın. ::: ## Ebeveyn ve miras alan profiller \{#parent-and-inheritor-profiles\} Aynı mağaza tarafındaki abonelik birden fazla Adapty profiliyle ilişkilendirildiğinde, Adapty bu profilleri bir zincir olarak ele alır: bir **ebeveyn** profil ve aynı satın almadan erişimi paylaşan bir ya da birden fazla **miras alan** profil. Bu durum şu koşullarda ortaya çıkar: - [Kullanıcı hesapları arasında ücretli erişim paylaşımı](sharing-paid-access-between-user-accounts) etkinleştirildiğinde ve bir kullanıcı, daha önce farklı bir profilin satın alma yaptığı bir cihazda oturum açtığında. - Bir kullanıcı uygulamayı `customer_user_id` olmadan yeniden yüklediğinde ve yeni profil önceki kurulumun satın almasını devraldığında. - Farklı tanımlı kullanıcılar aynı cihazda satın almaları geri yüklediğinde. - Bir uygulama Apple Team ID'leri arasında aktarıldığında ve yeni uygulama eski Team ID altında yapılan satın almaları devraldığında. **Üst öğenin nasıl seçildiği.** **Üst profil**, **satın alma işlemini ilk kaydeden profildir** — bu, profil oluşturma sırasına göre değil, Adapty'deki satın alma makbuzu sırasına göre belirlenir. Örneğin: uygulamayı yükleyip hiçbir satın alma yapmıyorsunuz, ardından yeniden yükleyip bir abonelik satın alıyorsunuz. İkinci profil, satın alma işlemini gerçekleştirdiği için üst profil olur. Birinci profil ise kalıtımcı olur ve paylaşım yoluyla erişim kazanır. **Olaylar nasıl dağıtılır:** - **İşlemsel olaylar** (satın almalar, yenilemeler, iptaller, faturalama sorunları, ek süreler, iade): Yalnızca satın almayı gerçekleştiren **üst profilde** görünür. Tüm abonelik yenilemeleri ve güncellemeleri bu profilde görünmeye devam eder. - **`access_level_updated` olayları**: Access level durumu her değiştiğinde **hem üst hem de devralan profillerde** görünür. Bu sayede bağlı tüm profiller güncel erişim durumlarından haberdar olur. Ana profil, işlem geçmişinin tamamını gösterir. Miras alan profiller ise yalnızca kendi access level güncellemelerini ve **Access level** bölümünde ana profile bir bağlantıyı gösterir. <img src="/assets/shared/img/98d0dad-non-original_profile.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> **Aynı aboneliği farklı profiller üzerinden takip etme.** Her miras alan profilin kendine ait bir `profile_id`'si vardır; bu nedenle `profile_id`, bir zincir boyunca tutarlı değildir. Aynı aboneliği birden fazla profil arasında tanımlamak için — örneğin webhook olaylarını eşleştirirken veya kontrol paneli profillerini tek bir kullanıcıyla ilişkilendirirken — bunun yerine mağaza tarafındaki tanımlayıcıyı kullanın. | Alan | Kullanım amacı | | --- | --- | | `store_original_transaction_id` | Profiller arasında bir abonelik zincirini tanımlamak için. Her Apple aboneliğine özel benzersiz bir değerdir. | | `profiles_sharing_access_level` (webhook alanı) | Paylaşım etkinleştirildiğinde, abonelik tarafından yetkilendirilen tüm profiller. | | `profile_id` | Profiller arası takip için **uygun değildir** — her devralan profilin kendine ait bir `profile_id`'si vardır. | ## Profil olmadan işlemler \{#transactions-without-profiles\} Adapty'deki bazı işlemler herhangi bir profile bağlı değildir — bunlar analitiklerde ve dışa aktarmalarda görünür, ancak Profiller listesinde yer almaz. Bu durum, Adapty SDK'sı aracılığıyla uygulamanıza hiç bağlanmamış kullanıcılara ait **sunucudan sunucuya (S2S) mağaza bildirimleri** için geçerlidir. Bilinen kaynaklar şunlardır: - App Store S2S bildirimleri (iade etkinlikleri dahil) - Google Play S2S bildirimleri - Stripe ve Paddle webhook etkinlikleri Bu işlemler: - **Analitik grafiklerde görünürler** (genel metriklere dahil edilirler) - **Dışa aktarımlarda görünürler** (S3, GCS, BigQuery) ve `profile_id` değerleri `null` olarak ayarlanır - **Profiller listesinde görünmezler** — bağlanacak bir profil yoktur Analitik veya dışa aktarımlarda, Profiller arayüzünde bulamadığınızdan daha fazla etkinlik görüyorsanız, bu fark büyük olasılıkla profile bağlı olmayan bu işlemlerden kaynaklanmaktadır. Bunları bir dışa aktarımda bulmak için `profile_id IS NULL` olan satırları filtreleyin. ## Kullanıcı hesapları arasında ücretli erişimi paylaşma \{#sharing-paid-access-between-user-accounts\} :::link Ana makale: [Kullanıcı hesapları arasında ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ::: Access level paylaşım politikanızı ayarlamak için [**General**](general) ayarlar sayfasında bir paylaşım seçeneği belirleyin. [Sandbox ortamı](test-purchases-in-sandbox) için ayrı bir politika ayarlayabilirsiniz. **Etkin (varsayılan)** Kimliği belirlenmiş kullanıcılar ([Müşteri Kullanıcı Kimliği](identifying-users#set-customer-user-id-on-configuration) atanmış olanlar), cihazları aynı Apple/Google ID ile oturum açmışsa Adapty tarafından sağlanan aynı [access level](access-level)'ı paylaşabilir. Bu, kullanıcının uygulamayı yeniden yükleyip farklı bir e-posta ile giriş yapması durumunda bile önceki satın alımına erişimini korumasını sağlar. Bu seçenekte birden fazla kimliği belirlenmiş kullanıcı aynı access level'ı paylaşabilir. Access level paylaşılıyor olsa da tüm geçmiş ve gelecekteki işlemler; deneme süreleri, abonelik satın alımları, yenilemeler ve daha fazlası dahil olmak üzere tutarlı bir analitik ve eksiksiz bir işlem geçmişi sağlamak amacıyla orijinal Müşteri Kullanıcı Kimliği'nde olay olarak kaydedilir ve aynı profile bağlı kalır. **Erişimi yeni kullanıcıya aktar** Kimliği belirlenmiş kullanıcılar, farklı bir [Müşteri Kullanıcı Kimliği](identifying-users#set-customer-user-id-on-configuration) ile giriş yapsalar veya uygulamayı yeniden yükleseler bile, cihazları aynı Apple/Google ID ile oturum açık olduğu sürece Adapty tarafından sağlanan [access level](access-level)'a erişmeye devam edebilir. Önceki seçenekten farklı olarak Adapty, satın alımı kimliği belirlenmiş kullanıcılar arasında aktarır. Bu sayede satın alınan içeriğe erişim sağlanır; ancak aynı anda yalnızca bir kullanıcı erişime sahip olabilir. Örneğin, KullanıcıA bir abonelik satın alır ve KullanıcıB aynı cihazda oturum açarak işlemleri geri yüklerse KullanıcıB aboneliğe erişim kazanırken KullanıcıA'nın erişimi iptal edilir. Kullanıcılardan biri (yeni veya eski) kimliği belirlenmemişse, access level yine de Adapty'deki bu profiller arasında paylaşılmaya devam eder. Access level aktarılıyor olsa da tüm geçmiş ve gelecekteki işlemler; deneme süreleri, abonelik satın alımları, yenilemeler ve daha fazlası dahil olmak üzere tutarlı bir analitik ve eksiksiz bir işlem geçmişi sağlamak amacıyla orijinal Müşteri Kullanıcı Kimliği'nde olay olarak kaydedilir ve aynı profile bağlı kalır. **Erişimi yeni kullanıcıya aktar** seçeneğine geçtikten sonra, access level'lar profiller arasında hemen aktarılmaz. Belirli bir access level için aktarım süreci; abonelik yenilemesi, geri yükleme veya işlem doğrulama gibi mağazadan bir olay alındığında tetiklenir. **Devre Dışı** Bir access level alan ilk kimliği belirlenmiş kullanıcı profili, bu erişimi kalıcı olarak elinde tutar. İş mantığınızın satın alımların tek bir Müşteri Kullanıcı Kimliği'ne bağlı olmasını gerektirdiği durumlarda en uygun seçenektir. Anonim kullanıcılar arasında access level paylaşımının devam ettiğini unutmayın. Bir satın alımı "ayırmak" için [kullanıcının profilini silebilirsiniz](https://adapty.io/docs/tr/api-adapty/operations/deleteProfile). Silme işleminin ardından access level, ister anonim ister kimliği belirlenmiş olsun, ilk talep eden kullanıcı profiline açık hale gelir. Paylaşımı devre dışı bırakmak yalnızca yeni kullanıcıları etkiler. Kullanıcılar arasında zaten paylaşılmakta olan abonelikler, bu seçenek devre dışı bırakıldıktan sonra da paylaşılmaya devam eder. :::warning Apple ve Google, uygulama içi satın alımların kullanıcılar arasında paylaşılmasını veya aktarılmasını zorunlu kılar; çünkü satın alımı belirli bir kullanıcıyla ilişkilendirmek için Apple/Google ID'ye güvenirler. Paylaşım olmadan, sonraki yeniden yüklemelerde satın alımların geri yüklenmesi çalışmayabilir. Paylaşımı devre dışı bırakmak, kullanıcıların giriş yaptıktan sonra erişimi yeniden kazanamamasına neden olabilir. Paylaşımı yalnızca kullanıcılarınızın satın alma yapmadan önce **giriş yapmasının zorunlu olduğu** durumlarda devre dışı bırakmanızı öneririz. Aksi takdirde, kimliği belirlenmiş bir kullanıcı abonelik satın alıp başka bir hesaba giriş yaparak erişimini kalıcı olarak kaybedebilir. ::: ### Hangi ayarı seçmeliyim? \{#which-setting-should-i-choose\} | Uygulamam... | Seçilecek seçenek | | ------------------------------------------------------------ | ------------------------------------------------------------ | | Giriş sistemi yok ve yalnızca Adapty'nin anonim profil ID'lerini kullanıyor. | Access level'lar her üç seçenekte de anonim profil ID'leri arasında her zaman paylaşıldığından varsayılan seçeneği kullanın. | | İsteğe bağlı giriş sistemine sahip ve müşterilerin hesap oluşturmadan önce satın alım yapmasına izin veriyor. | Hesapsız satın alım yapan müşterilerin işlemlerini daha sonra geri yükleyebilmesini sağlamak için **Erişimi yeni kullanıcıya aktar** seçeneğini belirleyin. | | Satın alım öncesinde hesap oluşturmayı zorunlu kılıyor ancak satın alımların birden fazla Müşteri Kullanıcı Kimliği'ne bağlanmasına izin veriyor. | Aynı anda yalnızca bir Müşteri Kullanıcı Kimliği'nin erişime sahip olmasını sağlarken kullanıcıların ücretli erişimlerini kaybetmeden farklı bir Müşteri Kullanıcı Kimliği ile giriş yapabilmesine olanak tanımak için **Erişimi yeni kullanıcıya aktar** seçeneğini belirleyin. | | Satın alım öncesinde hesap oluşturmayı zorunlu kılıyor ve satın alımları tek bir Müşteri Kullanıcı Kimliği'ne bağlayan katı kurallara sahip. | İşlemlerin hesaplar arasında hiçbir zaman aktarılmamasını sağlamak için **Devre Dışı** seçeneğini belirleyin. | ## Gelecek tarihli olay zaman damgaları (Apple/iOS) \{#event-timestamps-with-future-dates-appleios\} Bu davranış Apple App Store'a özgüdür. Google Play'in bildirim sistemi olayları önceden göndermez. Apple, yenileme olaylarını önceden gönderdiği için profillerdeki ve entegrasyonlardaki olay zaman damgaları gelecek tarihleri gösterebilir. - **Neden olur**: Apple bunu, aboneliklerin sona ermeden önce otomatik olarak yenilenmesini sağlamak ve kullanıcı hizmet kesintilerini önlemek için yapar. Daha fazla ayrıntı için Apple'ın Geliştirici Forumuna bakın: [Server Notifications for Subscriptions](https://developer.apple.com/forums/tags/app-store-server-notifications). - **Etkilenen olay türleri**: Genellikle bu durum abonelik yenilemeleri ve deneme sürümünden ücretli dönüşümleri için geçerlidir. Bu olaylar, Apple sistemleri önceden bilgilendirdiği için gelecek zaman damgalarına sahip olabilir. - **Diğer olay türleri**: Ek uygulama içi satın alımlar ve abonelik planı değişiklikleri, bu olaylar önceden tahmin edilemeyeceği için gerçek zaman damgalarıyla kaydedilir. - **Analitik ve Olay Akışı üzerindeki etkisi**: Bu olaylar yalnızca zaman damgaları geçtikten sonra **Analytics** ve **Event Feed**'de görünür. Gelecek zaman damgalı olaylar her iki bölümde de gösterilmez. - **Entegrasyonlar üzerindeki etkisi**: Adapty, olayları alır almaz entegrasyonlara gönderir. Bir olayın gelecek zaman damgası varsa Adapty, bunu entegrasyonunuza gelecek zaman damgası değiştirilmeden gönderir. ## Sonraki adımlar \{#next-steps\} - Kullanıcıları bulmak ve yönetmek için Profiller kontrol panelini kullanmak istiyorsanız [Profiller](profiles-crm) sayfasına bakın. - Uygulamanızda kullanıcı tanımlamayı ayarlamak için [kullanıcıları tanımlama](identifying-users) SDK kılavuzuna bakın. - Erişim paylaşım politikasını yapılandırmak için [Kullanıcı hesapları arasında ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) sayfasına bakın. --- # File: sharing-paid-access-between-user-accounts --- --- title: "Kullanıcı hesapları arasında ücretli erişimi paylaşma" description: "Birden fazla cihaza veya uygulama profiline sahip kullanıcılara hitap etmek için farklı kullanıcı hesapları arasında ücretli erişimi paylaşma" --- Bir kullanıcı satın alma yaptığında, Adapty aktif [profiline](identifying-users) yeni bir [access level](access-level) atar. Bu access level, alıcının ücretli içeriklere erişmesini sağlar. Kullanıcı uygulamayı yeniden yüklerse veya uygulama içinde yeni bir hesaba giriş yaparsa, alıcının profili istemeden değişebilir. Kesintisiz erişimi sağlamak için Adapty, kullanıcının access level'ını orijinal profil ile sonraki profiller arasında otomatik olarak paylaşır. Bu yaklaşım çoğu uygulama için idealdir. Ancak iş mantığınız gerektiriyorsa, daha kısıtlı bir ücretli erişim paylaşım politikası seçebilirsiniz. [Genel Ayarlar](https://app.adapty.io/settings/general) sayfasını açarak bir access level paylaşım politikası belirleyin. Test sürecini kolaylaştırmak için bu ayarı yalnızca [sandbox ortamı için](#sharing-paid-access-on-sandbox) değiştirebilirsiniz. <Details> :::important Uygulamanız kullanıcı kimlik doğrulaması yapmıyorsa bu ayarı göz ardı edebilirsiniz. Aynı mağaza hesabıyla ilişkilendirilen anonim profiller, access level'larını *her zaman* paylaşır. ::: <summary>Hangi erişim paylaşım politikasını seçmeliyim? (Genişletmek için tıklayın)</summary> | Uygulamam... | En iyi seçenek | | ------------------------------------------------------------ | ------------------------------------------------------------ | | Kimlik doğrulama özelliği yok ve yalnızca Adapty'nin anonim profil ID'lerini kullanıyor. | **Enabled (default)** ayarını kullanın. | | Kullanıcıları doğrulayabiliyor, ancak hesap oluşturmadan satın alma yapılmasına izin veriyor. | **Transfer access to new user** ayarını etkinleştirin. Kullanıcılar hesap açarak anonim satın almalarını üstlenebilir. | | Satın alma öncesi hesap oluşturulmasını zorunlu kılıyor, ancak tek bir ürünü birden fazla Customer User ID'ye bağlayabiliyor. | **Transfer access to new user** ayarını etkinleştirin. Birden fazla hesap ürüne erişebilir, ancak yalnızca sırayla. | | Satın alma öncesi hesap oluşturulmasını zorunlu kılıyor ve satın almaları tek bir Customer User ID'ye bağlayan katı kurallar uyguluyor. | Access level paylaşımını **devre dışı bırakın**. | </Details> <img src="/assets/shared/img/sharing-paid-access.webp" style={{ border: '1px solid #727272', /* border genişliği ve rengi */ width: '700px', /* görsel genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalama hizalama */ }} /> ## Enabled (default) \{#enabled-default\} Bu ayar, **yerleşik kimlik doğrulaması olmayan** uygulamalar için en iyi seçenektir. Satın alma işleminin ardından, aynı mağaza hesabıyla ilişkili tüm profiller access level'ı otomatik olarak *devralır*. * Kullanıcı uygulamanıza yeni bir kimlik bilgisi setiyle giriş yaparsa, ücretli içeriklere erişimini korur. * Kullanıcı fabrika ayarlarına sıfırladıktan sonra uygulamanızı yeniden yüklerse, ücretli içeriklere erişimini korur. * Kullanıcı, aynı mağaza hesabıyla farklı cihazlara uygulama yüklerse, satın alma tüm cihazlarda kullanılabilir hale gelir. Her uygulama örneğinin kendi müşteri profiline sahip olması durumunda bile. ## Transfer access to new user \{#transfer-access-to-new-user\} Bu ayar, **kimlik doğrulamalı ya da doğrulamasız** satın alıma izin veren veya **kullanıcı başına tek cihaz** politikası uygulamak isteyen uygulamalar için en iyi seçenektir. Adapty, satın alma erişimini aynı anda 1 müşteri kimliğiyle sınırlar. Cihaz sahibi uygulamayı yeniden yükleyebilir, oturum açıp kapatabilir; ancak aynı ürüne birden fazla müşteri kimliğinden aynı anda erişemez. Bu ayar etkinleştirildiğinde, anonim profiller (örneğin, kullanıcı oturum kapattıktan sonra aktif hale gelen bir profil) her zaman son aktif müşteri kimliğinin access level'ını devralır. Bu, ilerleyen süreçte erişim kaybını önlemek için gereklidir. :::warning Varsayılan ayarı devre dışı bırakıp **Transfer access to new user** seçeneğini etkinleştirdiğinizde, Adapty mevcut müşteri profillerinin access level'larını hemen güncellemez. Geçiş, bir kullanıcı yeni bir mağaza olayı tetiklediğinde gerçekleşir: örneğin, aboneliği yenilendiğinde veya satın alımlarını geri yüklediğinde. ::: :::important Adapty, eski profili yalnızca yeni profilde SDK işlemi ilettiği anda bir [Müşteri Kullanıcı Kimliği](identifying-users#set-customer-user-id-on-configuration) bulunduğunda iptal eder. `restorePurchases` anonim bir profil üzerinde çalışırsa, hem eski Müşteri Kullanıcı Kimliği hem de yeni anonim profil access level'a sahip olur. Eski profil daha sonra, anonim profili tanımladığınızda iptal edilir. Bunu önlemek için SDK metodlarını sırasıyla çağırın: `activate` → `identify` → `restorePurchases`. ::: ## Ücretli erişim paylaşımını devre dışı bırakma \{#disable-paid-access-sharing\} Bu ayar **yalnızca**, **zorunlu kimlik doğrulaması** olan veya bağımsız bir erişim yönetimi uygulaması kullanan uygulamalar için uygundur. Diğer durumlarda kullanıcılar satın alımlarına erişemeyebilir ve uygulamanız **zorunlu mağaza incelemesinde başarısız olma riskiyle** karşılaşabilir. Ücretli erişim paylaşımını devre dışı bıraktığınızda, Adapty ürünü satın alma anındaki aktif [müşteri kimliğine](identifying-users#set-customer-user-id-on-configuration) bağlar ve access level'ı başka hiçbir müşteri profiliyle paylaşmaz. Bu politika, katı 1'e 1 ürün dağıtımına olanak tanır. :::warning Ücretli erişim paylaşımını devre dışı bıraktığınızda, müşteri kimliklerinin ücretli erişimi devralmasını engellersiniz. Bir müşteri kimliği geçmişte ücretli erişimi devralmışsa, bu erişim otomatik olarak iptal edilemez. ::: :::important Acil durumlarda, bir sonraki kullanılabilir profilin (tanımlı ya da anonim) kendi access level'ını talep edebilmesi için [kullanıcı profilini silmeniz](api-adapty/operations/deleteProfile) gerekebilir. ::: ## Pratik referans \{#practical-reference\} Bir mod seçtikten sonra, aşağıdaki açıklamalar ne bekleyeceğinizi anlatır: hangi profiller erişimi görür, eski profil erişimi ne zaman kaybeder ve hangi webhook olayları tetiklenir. | Mod | Birden fazla profil aynı satın alımı paylaşabilir mi? | Transfer sırasında eski profilin erişimi iptal edilir mi? | Eski profilin erişimi ne zaman iptal edilir | İkinci bir profil aboneliği talep ettiğinde tetiklenen webhook olayları | | --- | --- | --- | --- | --- | | **Etkin (varsayılan)** | Evet — geri yükleme yapan veya oturum açan her profil erişimi devralır | Hiçbir zaman | Geçerli değil | Her yeni profil için `access_level_updated` (`is_active=true`) | | **Erişimi yeni kullanıcıya aktar** | Hayır — erişim özeldir ancak profiller arasında taşınabilir | Evet | Yeni tanımlanmış cihaz işlemi yayıldığında hemen (`restorePurchases`, identify veya sonraki mağaza tarafı olayı) | Yeni profil: `access_level_updated` (`is_active=true`). Eski profil: `access_level_updated` (`is_active=false`) | | **Devre dışı** | Hayır — satın alma başına kalıcı olarak bir Customer User ID | Geçerli değil — erişim hiçbir zaman aktarılmaz | Geçerli değil | İkinci profil için hiçbir olay tetiklenmez. SDK bu profil için erişim göstermez | ## Sandbox ortamında ücretli erişim paylaşımı \{#sharing-paid-access-on-sandbox\} Sandbox ortamı için özel bir ücretli erişim paylaşım politikası belirleyebilirsiniz. Sandbox ortamında satın alımları test ederken aşağıdaki davranışları bekleyin: * Apple, hesabınızın satın alma geçmişindeki önceki satın alımlarınızı saklar. Adapty SDK da bu bilgilere erişebilir. * Uygulamayı yeniden yüklerseniz ve Adapty ürünün daha önce satın alındığını tespit ederse, aktif profil access level'ı devralır. * Apple, ürün için mevcut bir satın alma tespit ederse, aktif profilin gerekli access level'a sahip olmadığı durumlarda bile aynı satın almayı iki kez yapmanıza izin vermez. Bu davranış, **ücretli erişim paylaşım ayarınızdan bağımsız olarak** gerçekleşir. Uygulamanız paywall'ı göstermez ve ürünü satın alamazsınız. Tek çözüm, **hesabınızın satın alma geçmişini temizlemektir**. Ayrıntılı talimatlar için [sandbox test kılavuzunu](test-purchases-in-sandbox) inceleyin. :::warning Apple sandbox ortamında abonelikler her birkaç dakikada bir otomatik yenilenir. Bu hızlı yenilemeler, Adapty'nin [üst profil](how-profiles-work#parent-and-inheritor-profiles) olarak kabul ettiği profili değiştirebilir — üretim ortamının nadiren yeniden oluşturduğu bir zincir deseni. Üretimde kullandığınız modu test edin ve sandbox'tan sonuç çıkarmadan önce davranışı gerçek bir Apple ID ile doğrulayın. ::: ## Analizlerde ücretli erişim paylaşımı \{#paid-access-sharing-in-analytics\} * Adapty, işlemleri gerçekleştikçe kaydeder. Tek bir işlem birden fazla profille ilişkilendirilebilir, ancak birden fazla kez sayılmaz. * İki veya daha fazla profil aynı access level'ı paylaşıyorsa, satın alma [üst profile](how-profiles-work#parent-and-inheritor-profiles) atfedilir. * Access level kalıtımı kurulum istatistiklerini etkilemez. Adapty'nin kurulumları nasıl saydığını belirlemek için ayarlar sayfasında mevcut iki [kurulum tanımından](installs#counting-modes) birini seçebilirsiniz. --- # File: segments --- --- title: "Segmentler" description: "Adapty'de daha iyi hedefleme için kullanıcı segmentleri oluşturun ve yönetin." --- **Segment**, ortak özelliklere sahip kullanıcıları gruplandıran bir filtreler kümesidir. Paywallları ve A/B testlerini daha etkili şekilde hedeflemek için segmentleri kullanın. :::note Etkinlik akışındaki olaylar kontrol paneline gecikmeli olarak ulaşır. Yeni profiller ve özellik değişiklikleri hemen görünmeyebilir. ::: Bir segment oluşturduktan sonra, hangi kullanıcıların hangi paywall'ı göreceğini kontrol etmek (tek veya birden fazla) için [bunu Placement'lar ve A/B testlerinde **kitle** olarak kullanabilirsiniz](audience). Örnekler: - Abonelik sahibi olmayanlara standart bir paywall gösterin; daha önce aboneliğini veya deneme süresini iptal etmiş kullanıcılara indirim teklif edin. - Farklı ülkelerden gelen kullanıcılara farklı paywall'lar gösterin. - Apple Search Ads attribution verilerine göre kullanıcıları hedefleyin. - Eski uygulama sürümlerindeki kullanıcılar mevcut paywall'ı görmeye devam ederken yeni sürümlerdeki kullanıcılar güncellenmiş olanı görsün. - [Analytics'te](controls-filters-grouping-compare-proceeds#filter-and-group-data), belirli kullanıcı gruplarının performansını görüntülemek için segmentlere göre filtreleyin. **All users** içindeki performansı veya katkıyı karşılaştırmak için segmente göre gruplandırın. <img src="/assets/shared/img/3244407-Segments.webp" style={{ border: 'none', /* kenarlık genişliği ve rengi */ width: '700px', /* görsel genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalı hizalama */ }} /> ## Oluşturma \{#creation\} Bir segment oluşturmak için bir ad girin ve filtrelerini belirleyen nitelikleri seçin. Birden fazla nitelik seçtiğinizde, kullanıcıların tüm koşulları karşılaması gerekir. Adapty, nitelikler arasında AND mantığı uygular. <img src="/assets/shared/img/1af9744-new_cohort.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Mevcut özellikler \{#available-attributes\} :::note Birçok kullanıcı özelliği otomatik olarak belirlense de (**Country** veya **Calculated total revenue USD** gibi), **Age**, **App user ID**, **Attribution** verisi, **Gender** ve **Custom attributes** otomatik olarak tanımlanmaz. Bunları segmentasyon amacıyla kullanmak istiyorsanız [kullanıcı özelliklerini ayarlamanız](setting-user-attributes) veya [attribution verisi iletmeniz](attribution-integration) gerekir. ::: :::tip Tarih tabanlı özellikler için şu filtreleri kullanabilirsiniz: - **Sabit tarih**: Takvimden belirli tarihler seçin (ör. Kara Cuma ile Siber Pazartesi arasında yükleme yapan kullanıcılara özel teklif gösterin) - **Göreli aralık**: "Son 7 gün" veya "Son 3 ay" gibi dinamik zaman aralıkları belirleyin (ör. 30+ gün önce görülen kullanıcıları yeniden kazanın ya da yeni yüklemeleri hedefleyin) Göreli aralıklar otomatik olarak güncellenir; bu da onları süregelen kampanyalar için ideal kılar. Sabit tarihler ise belirli bir süreyle sınırlı promosyonlar için daha uygundur. ::: | Özellik | Filtreleme kriteri | |---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Age** | Kullanıcının yaşı. Yaşın, Adapty tarafından ilk alındığı anda hesaplandığını ve sonradan güncellenmediğini unutmayın. | | **App User ID** | Kullanıcının uygulamanızdaki tanımlayıcısı ([customer_user_id](profiles-crm#user-attributes)). Örneğin, yalnızca giriş yapmamış kullanıcılara paywall göstermek istediğinizde bu alanın var olup olmadığına göre filtreleyebilirsiniz. | | **App version (current)** | Adapty'nin en son etkinlik verisi aldığı anda kullanıcının cihazında yüklü olan uygulamanın mevcut sürümü — kullanıcı güncelleme yaptıkça **güncellenir**, dolayısıyla her zaman o an çalışan sürümü gösterir. Belirli bir sürümü çalıştıran herkesi (bu sürüme daha önceki bir sürümden geçenler dahil) hedeflemek istediğinizde kullanın. Segment oluştururken **App version** yanındaki kalem ikonuna tıklayıp yeni bir sürüm ekleyerek hemen kullanabilirsiniz.<br/> **version > X.X** koşulu, her sürümü tek tek listelemek zorunda kalmadan belirli bir sürümden daha eski veya daha yeni tüm uygulama sürümlerinin dönüşüm etkisini ölçmenizi sağlar.<br/><br/> **Format:** Sürüm dizeleri [SemVer](https://semver.org/) formatına uymalıdır. Herhangi bir bölümdeki baştaki sıfırlar geçersizdir — `26.03.4` eşleşmez, `26.3.4` eşleşir. Geçersiz sürümler segmentten sessizce çıkarılır. | | **App version (on install)** | Adapty'nin ilk kez etkinlik verisi aldığı andaki, kullanıcının cihazında yüklü olan uygulama sürümü — kullanıcı güncelleme yapsa bile **o kuruluma sabitlenir ve hiçbir zaman güncellenmez**. Kullanıcıları mevcut sürümleri yerine ilk yükledikleri sürüme göre hedeflemek istediğinizde kullanın. `App version (on install) = 1.5.7` yalnızca ilk kurulumu 1.5.7 olan kullanıcılarla eşleşir; daha önceki bir sürümden 1.5.7'ye yükseltenler sessizce dışarıda kalır — güncelleyenleri de yakalamak için bunun yerine **App version (current)** kullanın.<br/><br/> **Format:** Sürüm dizeleri [SemVer](https://semver.org/) formatına uymalıdır. Herhangi bir bölümdeki baştaki sıfırlar geçersizdir — `26.3.04` eşleşmez, `26.3.4` eşleşir. Geçersiz sürümler segmentten sessizce çıkarılır. | | **Attribution: Ad Group** | Attribution reklam grubu. | | **Attribution: Ad Set** | Attribution reklam seti. | | **Attribution: Campaign** | Pazarlama kampanyasının adı. | | **Attribution: Creative** | Attribution kreatif anahtar kelimesi. | | **Attribution: Channel** | Pazarlama kanalının adı. | | **Attribution: Source** | Attribution'ın kaynağı. | | **Attribution: Status** | Attribution durumu. Olası değerler: <ul><li> **Organic** – Kullanıcı, ücretli herhangi bir pazarlama etkisi olmadan uygulamayı yükledi (örn. App Store/Google Play'de doğrudan arama, ağızdan ağıza yayılma veya organik sosyal medya erişimi).</li><li> **Non-organic** – Kullanıcı, ücretli bir pazarlama kanalı aracılığıyla kazanıldı (örn. reklamlar, influencer kampanyaları, yönlendirme programları).</li><li> **Unknown** – Bu kullanıcı için attribution verisi mevcut değil.</li></ul> | | **Calculated subscription state** | Kullanıcının [mevcut abonelik durumu](profiles-crm#subscription-state); aboneliğin aktif mi, iptal edilmiş mi olduğunu ya da çözüme kavuşturulmamış bir ödeme sorunu bulunup bulunmadığını gösterir. | | **Calculated total revenue USD** | Bu kullanıcının oluşturduğu toplam gelir. | | **Country** | Müşterinin ülkesi, en son IP adresine göre belirlenir. Adapty, IP sinyalini en fazla haftada bir yeniler; bu nedenle kullanıcı konum değiştirirse veya VPN kullanırsa farklılık oluşabilir. Bunun yerine kullanıcının App Store / Play Store hesap ülkesini hedeflemek için **Country from store account** kullanın. | | **Country from store account** | Kullanıcının iOS veya Android mağaza hesabıyla ilişkili ülke. Adapty'nin mağaza ülkesini yalnızca iOS 13 ve sonraki sürümlerde çalışan cihazlar için topladığını unutmayın. | | **Creation date** | Profilin oluşturulduğu tarih (uygulamanın kullanıcının cihazına ilk kez yüklendiği tarih). | | **Device** | Meta verilere dayalı cihaz türü. Örneğin 'Samsung Galaxy' veya 'iPhone 13'. | | **Gender** | Kullanıcının cinsiyeti. Bu değeri kendiniz belirlediğinizi unutmayın. | | **Installation date** | Kullanıcının uygulamayı yüklediği tarih. | | **Language** | Kullanıcının cihaz dili. <Callout type="warning">Adapty, dili 2 harfli `ISO 639-1` kodu olarak saklar. `zh-Hant-TW` veya `pt-BR` gibi genişletilmiş yerel ayarlar kullanmayın. Açılır menüde görünseler de hiçbir kullanıcıyla eşleşmezler.</Callout> <Callout type="tip">Dil hedeflemesini daha da daraltmak için **Language** ile **Country** koşullarını birleştirin. Örneğin **Simplified Chinese (`zh`)** + **Country = TW, HK, MO** kombinasyonu, Geleneksel Çince yazı kullanan kullanıcıları hedefler.</Callout> | | **Last seen** | Kullanıcının uygulamayı en son açtığı tarih. | | **OS** | Kullanıcının cihazının işletim sistemi sürümü. | | **Paid access level** | Kullanıcıya verilen access level. | | **Platform** | Kullanıcının cihaz platformu. Olası değerler: `iOS`, `macOS`, `iPadOS`, `visionOS`, `Android`. <br/> Kullanıcılar uygulamanıza birden fazla platformdan (örn. iOS ve Android) erişiyorsa, segment üyeliği her platform için o cihaza ait en güncel veriler kullanılarak ayrı ayrı değerlendirilir. Bu sayede aynı kullanıcı profili için bile platforma özgü hedefleme yapılabilir. | | **Subscription expiration date** | Aboneliğin sona erme tarihi ya da varlığı/yokluğu. Süresiz erişim satın alımları için `none` gösterir; kullanıcının bir profili olmasına rağmen hiç deneme süresi, abonelik veya süresiz satın alım yaşamamışsa boş kalır. | | **Subscription product** | Müşterinin aktif aboneliğinin en son ürün kimliği. | | **[Custom attributes](profiles-crm#custom-attributes)** | Uygulamanıza veya işletmenize özgü özelliklere dayalı, son derece hedeflenmiş segmentler oluşturmak için kendi özelliklerinizi tanımlayın. | ## Özel nitelikler \{#custom-attributes\} Uygulamanıza veya işletmenize özgü özelliklere dayalı daha hedefli segmentler oluşturmak için özel nitelikler tanımlayın. :::note - Özel nitelikleri mobil SDK'da veya Adapty Kontrol Paneli'nde ayarlayabilirsiniz. SDK kurulumu için [buraya](setting-user-attributes#custom-user-attributes) bakın. - Bir segmentte kullanılan özel niteliği sonradan değiştirirseniz, kullanıcı o segmentle [analizlerde](controls-filters-grouping-compare-proceeds#filter-and-group-data) senkrondan çıkabilir. Veriler önceki değeri yansıtmaya devam eder. ::: ### Özel bir attribute nasıl yapılandırılır \{#how-to-configure-a-custom-attribute\} Adapty Kontrol Paneli'nde, attribute açılır menüsünden **Create custom attributes** seçeneğini seçin. <img src="/assets/shared/img/883d3b2-CleanShot_2023-03-16_at_17.20.452x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> | Alan | Açıklama | | ------ |--------------------------------------------------------------------------------------------------------------------------------------| | **Name** | Adapty Kontrol Paneli'nde görünen özel nitelik etiketi. | | **Key** | Niteliğin benzersiz tanımlayıcısı. SDK'da kullanılan anahtarla eşleşmesi gerekir. | | **Type** | Aşağıdakilerden birini seçin:<ul><li>String: Önceden tanımlanmış olası değerler listesi gerektirir.</li><li>Number: Yalnızca sayısal değerleri kabul eder.</li></ul> | | **Values** | `String` seçerseniz olası değerlerin listesini girin. `Number` seçerseniz nitelik yalnızca sayısal girdi kabul eder. Sayısal nitelikler ondalık değerleri destekler ve karşılaştırma operatörleriyle kullanılabilir. | Gerekli alanları doldurduktan sonra, segment'lerinizde, [A/B testlerinde](ab-tests) ve daha fazlasında özel nitelikleri kullanabilirsiniz. Her profil en fazla 30 özel niteliğe sahip olabilir. ## Toplam kullanıcı sayısı ve rastgele örneklem \{#total-number-and-random-sample\} Bir segment oluşturduktan sonra Adapty, segment kriterlerine uyan toplam kullanıcı sayısını gösterir. Adapty ayrıca kriterlere uyan 40 kullanıcıdan oluşan rastgele bir örneklem de sunar. Segmentinizi test etmek ve doğru yapılandırıldığından emin olmak için bu örneklemi kullanabilirsiniz. <img src="/assets/shared/img/segment-random-set.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Segmentleri kopyalama \{#duplicate-segments\} Mevcut bir segmente benzer bir segment oluşturmanız gerekiyorsa, sıfırdan oluşturmak yerine kopyalayın. Bu, örtüşen kullanıcı gruplarıyla birden fazla kampanya veya A/B testi yürüten ekipler için zaman kazandırır. Bir segmenti kopyaladığınızda, tüm filtreleri ve açıklamasıyla birlikte bir kopyası oluşturulur. Yeni segmentin adına "(copy)" eklenerek orijinalden ayırt edilmesi sağlanır. Yeni segment, orijinalden bağımsızdır. Birinde yapılan değişiklikler diğerini etkilemez. Adapty Kontrol Paneli'nde bir segmenti kopyalamak için: 1. Adapty ana menüsünde **Profiles & Segments** bölümünü açın ve [**Segments**](https://app.adapty.io/segments) sekmesine geçin. 2. Segmentin yanındaki **3-dot** düğmesine tıklayın ve **Duplicate** seçeneğini seçin. <img src="/assets/shared/img/duplicate-segment.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Yeni segmenti açın ve filtrelerini ihtiyacınıza göre düzenleyin. ## Segmentleri silme \{#delete-segments\} Bir segmente artık ihtiyaç duymadığınızda, onu kalıcı olarak silebilirsiniz. Segment şu durumlardan herhangi birinde kitle olarak kullanılıyorsa Adapty silme işlemini engeller: - **Bir placement**: En az bir silinmemiş placement, segmenti kitle olarak kullanıyordur. - **Bir A/B testi (Canlı veya Tamamlanmış)**: En az bir silinmemiş A/B testi, segmenti kitle olarak kullanıyordur. Segment silindiğinde, Adapty hem **Live** hem de **Completed** A/B testlerini aktif olarak değerlendirir. Tamamlanmış bir test, eşleşen kullanıcılara test sonrası paywall veya onboarding'i göstermek için kitleyi kullanmaya devam eder ve teste ait geçmiş metrikler söz konusu segmente göre kapsamlandırılır. Segment ancak A/B testinin kendisi silindiğinde serbest bırakılır. :::warning Segment silme işlemi kalıcıdır. Segment geri yüklenemez. ::: Adapty Kontrol Paneli'nde bir segment silmek için: 1. Adapty ana menüsünde **Profiles & Segments** bölümüne gidin ve [**Segments**](https://app.adapty.io/segments) sekmesine geçin. 2. Segmentin yanındaki **3 nokta** düğmesine tıklayın ve **Delete** seçeneğini seçin. 3. Onay alanına segment adını yazın, ardından **Delete forever** düğmesine tıklayın. :::info Segment kullanımdaysa, diyalog onu kullanan placement'ları ve A/B testlerini listeler. Silme işlemini açmak için listedeki her placement veya A/B testini açın ve ya segmenti kitlesinden kaldırın ya da placement'ı ya da A/B testini tamamen silin. Hiçbir şey segmente başvurmadığında, segmenti silebilirsiniz. ::: --- # File: event-feed --- --- title: "Etkinlik akışı" description: "Adapty'nin etkinlik akışı ile kullanıcı aktivitesini izleyin ve analiz edin." --- Etkinlik akışı, Adapty tarafından oluşturulan [Etkinlikleri](events) görsel olarak takip etmenizi ve webhook dahil üçüncü taraf entegrasyonlara aktarım durumlarını kontrol etmenizi sağlar. :::warning Event Feed şunları göstermez: - **Sunucu tarafı API v1 işlemleri**: [Sunucu tarafı API (sürüm 1)](server-side-api-specs-legacy#requests) kullanılarak oluşturulanlardır. Bunların görünmesi için bunun yerine [sunucu tarafı API (sürüm 2)](api-adapty/operations/setTransaction) kullanın. - **Profili olmayan olaylar**: SDK bir kullanıcıyı tanımlamadan önce gelen işlemler — örneğin, mağaza sunucu bildirimleri. Bunları dışa aktarmalara dahil etmek için [S3](s3-exports) veya [Google Cloud Storage](google-cloud-storage) entegrasyonunda **Include events without profile** seçeneğini etkinleştirin. ::: <img src="/assets/shared/img/event-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note AppsFlyer, Facebook Ads ve Branch gönderim durumu yanlış olabilir; çünkü bu platformlar her zaman hata oluştuğunda bunu bildirmez. ::: İşlemi başlatan kullanıcının profilini görüntülemek için etkinlik ayrıntılarındaki **View Profile** düğmesine tıklayın. --- # File: ab-tests --- --- title: "A/B testi" description: "Adapty'de A/B testleri ile abonelik fiyatlandırmasını optimize ederek dönüşüm oranlarını artırın." --- :::tip Araştırma yapmadan eyleme dönüştürülebilir bir A/B testi planı elde edebilirsiniz. [AI Growth Advisor](autopilot), paywallınızı denetler, rakiplerinizle kıyaslar ve Adapty'nin takip ettiği 20.000 abonelik uygulamasından elde edilen anonimleştirilmiş verilerden öneriler üretir. ::: Adapty'de A/B testleri çalıştırarak uygulama gelirinizi artırın. Hangi seçeneğin en iyi dönüşüm sağladığını bulmak için farklı flow'ları, paywall'ları ve onboarding'leri karşılaştırın — kod değişikliği gerekmez. Örneğin şunları test edebilirsiniz: - Abonelik fiyatları - Paywall tasarımı, metinleri ve düzeni - Deneme süreleri ve abonelik süreleri - Onboarding tasarımları ## Ön Koşullar \{#prerequisites\} A/B testi oluşturmadan önce şunlara sahip olmanız gerekir: - **Placement'lar**: Bir flow, paywall veya onboarding'in gösterildiği bir veya daha fazla [placement](placements). - **Flow'lar için**: En az iki [flow](adapty-flow-builder). - **Paywall'lar için**: En az iki [paywall](paywalls). - **Onboarding'ler için**: En az iki [onboarding](onboardings). :::warning [Adapty Flow builder](adapty-flow-builder) veya [Adapty Paywall builder](adapty-paywall-builder) kullanmıyorsanız, paywall görüntülemelerini `.logShowFlow()` (iOS SDK v4+) / `.logShowPaywall()` ile [Adapty'e gönderin](present-remote-config-paywalls#track-paywall-view-events). Bu metod olmadan Adapty, testteki paywall görüntülemelerini hesaplayamaz ve dönüşüm istatistikleri hatalı olur. ::: ## A/B testi türleri \{#ab-test-types\} Adapty iki ana A/B testi türünü destekler: - **Regular**: Tek bir flow/paywall/onboarding placement üzerinde çalışır. - **Crossplacement**: Birden fazla paywall placement'ı üzerinde çalışır ve kullanıcıya her yerde aynı varyantı gösterir. Şu anda yalnızca paywall'lar için kullanılabilir. Türlerin, kullanım senaryolarının ve öncelik kurallarının tam karşılaştırması için bkz. [A/B testi türleri](ab-test-types). ## Sonraki adımlar \{#next-steps\} - [AI Growth Advisor](autopilot) — Paywallınızı analiz edin, pazar içgörüleri edinin ve bir A/B testi planı oluşturun - [A/B testi türleri](ab-test-types) — Test türleri ve her birinin ne zaman kullanılacağı hakkında bilgi edinin - [A/B testi oluşturma, çalıştırma ve durdurma](run_stop_ab_tests) — İlk testinizi kurun ve çalıştırın - [A/B testi sonuçları ve metrikler](results-and-metrics) — A/B testi verilerinizi anlayın ve kazananı belirleyin --- # File: ab-test-types --- --- title: "A/B testi türleri" description: "Adapty'deki A/B testi türleri hakkında bilgi edinin." --- Adapty, farklı test senaryolarına uygun iki A/B testi türü sunar: - **Normal A/B testi:** Tek bir [flow](adapty-flow-builder)/[paywall](paywalls)/[onboarding](onboardings) placement'ı için oluşturulan A/B testi. - **Çapraz placement A/B testi:** Uygulamanızdaki birden fazla paywall placement'ı için oluşturulan A/B testi. A/B testi bir <InlineTooltip tooltip="varyant">A/B testi varyantları, test edilecek flow, paywall veya onboarding'in alternatif versiyonlarıdır.</InlineTooltip> atadıktan sonra, bu varyantı uygulamanızın seçilen tüm bölümlerinde tutarlı biçimde gösterir. :::warning Crossplacement A/B testleri yalnızca Adapty SDK'nın v3.5.0 ve sonraki sürümleriyle kullanılabilir. Crossplacement A/B testleri yalnızca paywall'larla çalışır. Flow A/B testleri için Adapty SDK v4.0.0+ gereklidir. Onboarding A/B testleri için Adapty SDK v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity) veya v3.15.0+ (Kotlin Multiplatform, Capacitor) gereklidir. Önceki sürümlerdeki kullanıcılar bu testleri atlar. ::: Her flow/paywall/onboarding, test sırasında trafiği bölmek için bir ağırlık alır. Örneğin %70 ve %30 ağırlıklarıyla, ilk paywall yaklaşık 1.000 kullanıcının 700'üne, ikincisi ise 300'üne gösterilir. Crossplacement testlerinde ağırlıklar paywall başına değil, varyant başına ayarlanır. Bu yapı, farklı flow'ları ve paywallları karşılaştırmanıza ve uygulamanızın para kazanma stratejisi için veriye dayalı kararlar almanıza olanak tanır. ## Her türü ne zaman kullanmalı \{#when-to-use-each-type\} Her A/B testi türü şu durumlarda kullanışlıdır: - **Düzenli A/B testleri**: - Uygulamanızda yalnızca bir placement bulunuyorsa. - A/B testinizi yalnızca tek bir placement üzerinde çalıştırmak ve uygulamanızda birden fazla placement olsa bile yalnızca o placement için ekonomik değişiklikleri takip etmek istiyorsanız. - A/B testini eski kullanıcılar üzerinde çalıştırmak istiyorsanız (en az bir Adapty paywall görmüş kullanıcılar). - **Crossplacement A/B testi**: - Varyantları birden fazla placement genelinde senkronize etmek istiyorsanız. Örneğin, onboarding flow'undaki ve uygulamanızın ayarlarındaki fiyatları aynı anda değiştirebilirsiniz. - Uygulamanızın genel ekonomisini değerlendirmek istiyorsanız. Testi tüm placement'larda çalıştırmak, A/B testi istatistiklerini yalnızca izole placement'ları test etmeye kıyasla analiz etmeyi kolaylaştırır. - A/B testini yalnızca yeni kullanıcılar, yani hiç Adapty paywall görmemiş kullanıcılar üzerinde çalıştırmak istiyorsanız. - Tek bir varyant içinde birden fazla paywall kullanmak istiyorsanız: <img src="/assets/shared/img/ab-test-variants.png" alt="Tek bir crossplacement A/B testi varyantında birden fazla paywall örneği" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Temel farklar \{#key-differences\} | Özellik | Normal A/B Testi | Crossplacement A/B Testi | | ------------------------------- |--------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| | **Test edilen şey** | Tek bir flow/paywall/onboarding | Bir varyanta ait paywall seti | | **Varyant tutarlılığı** | Varyant her placement için ayrı ayrı belirlenir | Tüm paywall placement'larında aynı varyant kullanılır | | **Kitle hedefleme** | Her flow/paywall/onboarding placement'ı için ayrı tanımlanır | Tüm paywall placement'larında ortaktır | | **Analitik** | Tek bir flow/paywall/onboarding placement'ını analiz edersiniz | Testin parçası olan placement'larda uygulamanın tamamını analiz edersiniz | | **Varyant ağırlık dağılımı** | Her flow/paywall/onboarding için ayrı | Paywall seti başına | | **Kullanıcılar** | Tüm kullanıcılar için | Yalnızca yeni kullanıcılar (daha önce Adapty paywallı görmemiş olanlar) | | **Adapty SDK sürümü** | Flow'lar için: v4.0.0+. Paywall'lar için: herhangi bir sürüm. Onboarding'ler için: v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity), v3.15.0+ (KMP, Capacitor) | 3.5.0+ | | **En iyi kullanım durumu** | Genel uygulama ekonomisini gözetmeksizin tek bir flow/paywall/onboarding placement'ındaki bağımsız değişiklikleri test etmek | Uygulama genelinde genel para kazanma stratejilerini değerlendirmek | ## A/B testi seçim mantığı \{#ab-test-selection-logic\} **Crossplacement A/B testleri, regular A/B testlerinden önceliklidir.** Ancak Crossplacement testleri yalnızca **yeni kullanıcılara** gösterilir; yani daha önce hiç Adapty paywall'ı görmemiş olanlara (`getPaywall` SDK metodu hiç çağrılmamış olanlara). Bu, placement'lar arasında sonuçların tutarlı olmasını sağlar. Aşağıdaki diyagram, Adapty'nin bir placement için A/B testi seçmekte kullandığı mantığı göstermektedir: <img src="/assets/shared/img/ab-tests-scheme.webp" alt="Bir paywall placement için A/B testi seçim mantığını gösteren diyagram" style={{ border: '1px solid #727272', /* border width and color */ width: '350px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **A/B Tests** sayfasında paywall, onboarding, flow ve Crossplacement testleri ayrı sekmelerde görüntülenir. <img src="ab-tests-tabs.webp" alt="Regular, Onboarding ve Crossplacement test türleri için sekmeler içeren A/B testi listesi sayfası" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Çapraz-placement A/B testi kısıtlamaları \{#crossplacement-ab-test-limitations\} :::warning Çapraz-placement A/B testleri, flow veya onboarding placement'larını içeremez. ::: Çapraz-placement A/B testleri, her kullanıcının testteki tüm placement'larda aynı varyantı görmesini garanti eder. Bu durum aşağıdaki kısıtlamaları beraberinde getirir: * Yalnızca yeni kullanıcılar katılabilir. Yeni kullanıcı; daha önce hiç Adapty paywalli görmemiş ve uygulaması hiç `getPaywall` çağrısı yapmamış kişidir. Adapty, diğer kullanıcılar için tutarlı bir paywall zinciri garanti edemez. * Kullanıcının karşılaştığı ilk placement, Adapty'nin hangi paywall'ı göstereceğini belirler. Kullanıcının atamasını değiştiremez ya da aynı kullanıcıyı birden fazla Crossplacement A/B testine dahil edemezsiniz. :::warning Bir kullanıcı Crossplacement paywall'ı aldıktan sonra, testi durdursanız bile 90 gün boyunca o paywall'ı görmeye devam eder. Bu süreyi değiştirmek için **General** ayarlarında **[Cross-placement variation stickiness](general#9-cross-placement-variation-stickiness)** seçeneğini düzenleyin. ::: ## Crossplacement A/B testi önceliği \{#crossplacement-ab-test-priority\} * Crossplacement A/B testleri her zaman regular ve onboarding A/B testlerinden önceliklidir. Yeni bir kullanıcı aynı placement'ta hem bir Crossplacement testiyle hem de bir regular testle eşleşiyorsa Crossplacement testi gösterilir. * Aynı kitleyi hedefleyen birden fazla Crossplacement A/B testi aynı placement'ı paylaşıyorsa Adapty, test önceliğini eklenme sırasına göre otomatik olarak belirler. İlk eklenen test en yüksek önceliği alır. Bunu manuel olarak değiştiremezsiniz. * Kitlenizin daha küçük segmentlerini hedefleyen testler, Tüm Kullanıcılar segmentini hedefleyenlere göre otomatik olarak öncelik kazanır. :::note Analytics'te bir Crossplacement A/B testi, her placement için birer alt test olmak üzere birkaç alt test olarak görünür. Alt testler `<test-adı> child-0`, `<test-adı> child-1` şeklinde adlandırılır. Numaralandırma, A/B testi detay sayfasındaki placement sırasıyla eşleşir. Belirli bir placement'ın sonuçlarını görüntülemek için **Placement** filtresini kullanın. ::: ## Sonraki adımlar \{#next-steps\} - [A/B testi oluşturma, çalıştırma ve durdurma](run_stop_ab_tests) — İlk testinizi kurun ve başlatın - [A/B testi sonuçları ve metrikleri](results-and-metrics) — Performansı analiz edin ve kazananı seçin --- # File: run_stop_ab_tests --- --- title: "A/B testi oluşturma, çalıştırma ve durdurma" description: "Adapty'de A/B testi oluşturma, çalıştırma ve durdurma için adım adım kılavuz." --- Bu makale, Adapty'deki bir A/B testinin tam yaşam döngüsünü ele alır: test oluşturma, çalıştırma ve sonuçları incelemeye hazır olduğunuzda durdurma. ## Ön Koşullar \{#prerequisites\} Bir A/B testi kurmadan önce şunlara sahip olmanız gerekir: - En az iki [flow](adapty-flow-builder)/[paywall](paywalls)/[onboarding](onboardings) oluşturulmuş olmalı - Uygulamanızda yapılandırılmış bir [placement](placements) bulunmalı :::warning [Adapty Flow builder](adapty-flow-builder) veya [Adapty Paywall builder](adapty-paywall-builder) kullanmıyorsanız, [paywall görüntülemelerini Adapty'e gönderin](present-remote-config-paywalls#track-paywall-view-events) (`.logShowPaywall()` ile). Bu metot olmadan Adapty, testteki paywall görüntülemelerini hesaplayamaz ve dönüşüm istatistikleri hatalı olur. ::: :::info Adapty'deki A/B testleri iki adımlı bir flow izler. Önce bir test oluşturur ve taslak olarak kaydedersiniz — hemen yayına girmez. Hazır olduğunuzda ayrıca çalıştırırsınız. Bu sayede kullanıcılar görmeden önce kurulumu inceleyebilirsiniz. ::: ## A/B testi oluşturma \{#create-an-ab-test\} Yeni bir A/B testi oluştururken en az iki [flow](adapty-flow-builder)/[paywall](paywalls)/[onboarding](onboardings) eklemeniz gerekir. Yeni bir A/B testi oluşturmak için: 1. Adapty ana menüsünden [A/B tests](ab-tests) bölümüne gidin. <img src="/assets/shared/img/go-to-abtests.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Sağ üst köşede **Create A/B test** düğmesine tıklayın. <img src="/assets/shared/img/create-abtest.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **A/B testi oluştur** penceresinde bir **Test adı** girin. Bu alan zorunludur. Sonuçları incelerken tespit edebilmek için testin ne hakkında olduğunu açıkça belirten bir ad seçin. 4. Neye ulaşmak istediğinizi açıklamak için **Test hedefi** alanını doldurun (örneğin, abonelikleri artırmak veya kayıpları azaltmak). 5. **Placement seç**'e tıklayın ve bir flow, paywall veya onboarding placement'ı seçin. 6. **Varyantlar** tablosunda test içeriğini ayarlayın. Her satır bir varyantı, her sütun bir placement'ı temsil eder. Her kesişim noktasına bir paywall ekleyin. Varsayılan olarak, tablo 2 varyant ve 1 placement içerir. En fazla 20 varyant ekleyebilirsiniz. İkinci bir placement eklediğinizde test, Crossplacement A/B testine dönüşür. Crossplacement A/B testlerinin yalnızca paywall'lar için kullanılabildiğini unutmayın. <img src="/assets/shared/img/abtest-variants.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 7. Testinizi kaydedin. İki seçeneğiniz var: 1. **Save as draft**: Test hemen yayına girmez. Placement veya A/B testi listesinden daha sonra başlatabilirsiniz. Yayına almadan önce kurulumu gözden geçirmek için kullanın. 2. **Run A/B test**: Testi hemen başlatır. Bu düğmeye tıkladığınız anda test yayına girer. Taslak olarak kaydettikten sonra [A/B testi çalıştırma](#run-an-ab-test) adımına geçin. ## A/B testini düzenleme \{#edit-an-ab-test\} Yalnızca taslak olarak kaydedilmiş A/B testlerini düzenleyebilirsiniz. Test yayına girdikten sonra değişiklik yapılamaz. Yayındaki bir testi güncellemek için **Modify** seçeneğini kullanın — bu, aynı adla bir kopya oluşturur ve üzerinde değişiklik yapabilirsiniz. Adapty orijinal testi durdurur; hem orijinal hem de değiştirilmiş sürümler analitikte ayrı ayrı görünür. ## A/B testi çalıştırma \{#run-an-ab-test\} Adapty'de bir A/B testi çalıştırmak, kullanıcılara paywall ve onboarding göstermeye başlayabilmesi için testin bir placement'a atanması anlamına gelir. 1. Adapty ana menüsünden [A/B tests](ab-tests) bölümüne gidin. 2. Doğru listeyi görüntülediğinizden emin olun — **Paywall**, **Flow**, **Onboardings** ve **Crossplacement** A/B testleri, aralarında geçiş yapabileceğiniz ayrı sekmelerde gösterilir. 3. **Drafts** sekmesine geçin. Yalnızca taslak testler başlatılabilir. 4. Başlatmak istediğiniz testin yanında **Run A/B test** düğmesine tıklayın. <img src="/assets/shared/img/run-ab-test-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Edit A/B test** penceresi açılır. Kurulumu gözden geçirin ve son değişiklikleri yapın. Placement veya kitle eksikse şimdi ekleyin. 6. Kurulumu inceledikten sonra başlatmak için **Run A/B test** düğmesine tıklayın. Testi başlattıktan sonra, [A/B testi sonuçları ve metrikleri](results-and-metrics) sayfasında ilerlemeyi takip edebilir ve performans verilerini görüntüleyebilirsiniz. ## A/B testini durdurma \{#stop-an-ab-test\} Bir A/B testini durdurduğunuzda test sona erer ve sonuçları inceleyebilirsiniz. Ayrıca test bittikten sonra etkilenen placement'larda kullanıcılara neyin gösterileceğine karar verirsiniz. <img src="/assets/shared/img/stop-ab-test.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. [A/B tests](https://app.adapty.io/ab-tests) bölümünü açın ve **Live** sekmesine gidin. 2. Durdurmak istediğiniz testin yanındaki üç nokta menüsüne tıklayın, ardından **Stop A/B test** seçeneğini seçin. 3. **Stop the A/B test** penceresinde test sona erdikten sonra ne olması gerektiğine karar verin. Üç seçeneğiniz var: | Seçenek | Açıklama | |---------|----------| | Test edilen paywall/onboarding'lerden birini göster | Test sonuçlarına (gelir, en iyi olma olasılığı (**P2BB**) ve 1K kullanıcı başına gelir gibi) göre kazanan paywall veya onboarding'i seçin. Bu paywall veya onboarding, seçili placement ve kitle için gösterilecektir. | | A/B testine katılmayan paywall/onboarding seç | Mevcut A/B testinin parçası olmayan herhangi bir paywall veya onboarding seçin. Test edilen varyantların hiçbiri hedeflerinizi karşılamadığında bunu kullanın. | | Belirli bir paywall/onboarding gösterme | Seçili placement ve kitle için A/B testi sona erdikten sonra belirli bir paywall veya onboarding seçilmez. Bunun yerine, kitle önceliğine göre bir sonraki uygun paywall veya onboarding gösterilir. Manuel seçim yapmak yerine mevcut kurulumunuzun hangi paywall veya onboarding'i göstereceğine karar vermesini tercih ediyorsanız bu iyi bir seçenektir. | :::note A/B testini durdurmak geri alınamaz — test yeniden başlatılamaz. Durdurmaya karar vermeden önce yeterli veri topladığınızdan emin olun. ::: 4. **Stop and complete this A/B test** düğmesine tıklayın. A/B testi tamamlandığında artık aktif olmayacak ve içindeki paywall veya onboarding'ler yeni kullanıcılara gösterilmeyecektir. Test çalışırken katılan kullanıcıların performansını incelemek için [A/B testi metrikleri sayfasındaki](results-and-metrics#metrics-controls) sonuç ve metriklere erişmeye devam edebilirsiniz. Yeni satın alma veya gelir olayları bu kullanıcılara atfedildikçe metrikler güncellenmeye devam edebilir. --- # File: ab-test-no-paywall-variants --- --- title: "Flow veya paywall olmadan A/B testi varyantları ekleme" description: "Bir varyantın flow veya paywall'ı atladığı bir A/B testi çalıştırın; gösterilip gösterilmeyeceğini kontrol etmek için remote config bayrağı kullanın." --- Flow veya paywall'ınızın etkisini boş bir varyanta karşı A/B testi yaparak ölçebilirsiniz. Bir varyant flow/paywall'ı gösterir; diğeri hiçbir şey göstermez. Uygulamanız, render edip etmeyeceğine karar vermek için remote config'den bir bayrak okur. ## Nasıl çalışır \{#how-it-works\} Kurulum, aynı placement içinde iki flow/paywall kullanır: - **Flow/Paywall A**: Test etmek istediğiniz flow veya paywall; remote config'inde `show_paywall` değeri `true` olarak ayarlanmıştır. - **Flow/Paywall B**: Remote config'inde `show_paywall` değeri `false` olarak ayarlanmış, boş bir flow veya paywall. SDK bir flow veya paywall döndürdüğünde uygulamanız `show_paywall` bayrağını okur. Bayrak `true` ise uygulama onu render eder. Bayrak `false` ise uygulama render işlemini atlar ve kullanıcı hiçbir şey görmeden devam eder. ## 1. Placement'teki show_paywall bayrağını remote config'e ekleyin \{#1-add-the-show_paywall-flag-in-remote-config\} Aynı placement içinde iki flow veya paywall'a ihtiyacınız var: Flow/Paywall A (test etmek istediğiniz) ve Flow/Paywall B (boş olan). Her ikisine de `show_paywall` alanı ekleyerek uygulamanızın her iki varyant için de aynı anahtarı kullanmasını sağlayın. Bayrağı Flow/Paywall A'ya eklemek için: 1. Adapty ana menüsünde [**Flows**](https://app.adapty.io/flows)/[**Paywalls**](https://app.adapty.io/paywalls) bölümünü açın ve Flow/Paywall A'yı seçin. 2. **Remote config** bölümünü açın. 3. `show_paywall` adında ve `true` değerinde bir alan oluşturun. **JSON** görünümünde bu giriş şöyle görünür: ```json showLineNumbers { "show_paywall": true } ``` 4. Değişiklikleri kaydedin. Aynı adımları Flow/Paywall B için tekrarlayın; ancak `show_paywall` değerini `false` olarak ayarlayın. Remote config hakkında daha fazla bilgi için [Remote config ile flow'u özelleştirme](customize-flow-with-remote-config) veya [Remote config ile paywall tasarlama](customize-paywall-with-remote-config) sayfalarına bakın. :::tip Her iki varyantta da `show_paywall` ayarlamak, her iki grup için kod akışını özdeş tutar ve testi daha sonra daha fazla varyantla genişletmeyi kolaylaştırır. ::: ## 2. A/B testini kurma \{#set-up-the-ab-test\} 1. Placement üzerinde [bir A/B testi oluşturun](run_stop_ab_tests) ve her iki flow/paywall'ı varyant olarak ekleyin. 2. Flow/paywall'ı görüntüleyen kullanıcılar ile görmeyenler arasındaki trafiği bölmek için varyant ağırlıklarını ayarlayın. ## 3. Uygulamanızda bayrağı kontrol edin \{#check-the-flag-in-your-app\} SDK tarafından döndürülen remote config'den `show_paywall` değerini okuyun. Bayrak `false` ise render işlemini atlayın ve kullanıcının devam etmesine izin verin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let config = flow.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow.remoteConfigs.first let showPaywall = config?.dictionary?["show_paywall"] as? Bool ?? true if showPaywall { // flow veya paywall'ı göster } } catch { // hatayı işle } ``` </TabItem> <TabItem value="kotlin" label="Android"> ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value val showPaywall = paywall.remoteConfig?.dataMap?.get("show_paywall") as? Boolean ?: true if (showPaywall) { // Render the paywall } } is AdaptyResult.Error -> { // handle the error } } } ``` </TabItem> <TabItem value="react-native" label="React Native"> ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: "YOUR_PLACEMENT_ID" }); const showPaywall = paywall.remoteConfig?.data?.["show_paywall"] ?? true; if (showPaywall) { // Paywall'ı göster } } catch (error) { // hatayı işle } ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final bool showPaywall = paywall.remoteConfig?.dictionary?['show_paywall'] as bool? ?? true; if (showPaywall) { // Paywall'ı göster } } on AdaptyError catch (adaptyError) { // hatayı işle } ``` </TabItem> <TabItem value="unity" label="Unity"> ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } var showPaywall = paywall.RemoteConfig?.Dictionary?["show_paywall"] as bool? ?? true; if (showPaywall) { // Render the paywall } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform"> ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID" ).onSuccess { paywall -> val showPaywall = paywall.remoteConfig?.dataMap?.get("show_paywall") as? Boolean ?: true if (showPaywall) { // Render the paywall } }.onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor"> ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID' }); const showPaywall = paywall.remoteConfig?.data?.['show_paywall'] ?? true; if (showPaywall) { // Render the paywall } } catch (error) { // handle the error } ``` </TabItem> </Tabs> Yedek değer olan `true`, bayrak eksik olduğunda flow/paywall'ın görünür kalmasını sağlar; bu sayede bayrağı olmayan mevcut flow'lar/paywall'lar etkilenmez. :::important Eğer paywall'u kendiniz render ediyorsanız ([Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) kullanmadan), Flow/Paywall A'yı görüntülediğinizde [`logShowFlow` (iOS SDK v4+) / `logShowPaywall`](present-remote-config-paywalls#track-paywall-view-events) metodunu çağırın. Bu olmadan Adapty, testteki görüntülemeleri sayamaz. Flow/Paywall B hiç gösterilmediği için onun için görüntüleme kaydı yapmayın. ::: ## Sonraki adımlar \{#next-steps\} - [A/B testi oluşturma, çalıştırma ve durdurma](run_stop_ab_tests) — Her iki varyantı da içeren testi kurun - [A/B testi sonuçları ve metrikler](results-and-metrics) — Boş varyantı flow/paywall'unuzla karşılaştırın --- # File: results-and-metrics --- --- title: "A/B testi sonuçları ve metrikleri" description: "Uygulamanızın abonelik performansını ve kullanıcı etkileşimini iyileştirmek için Adapty'deki sonuçları ve temel metrikleri analiz edin." --- [A/B testleri](ab-tests)nden elde ettiğiniz önemli verileri ve içgörüleri keşfedin; farklı paywall'ları ve onboarding'leri karşılaştırarak kullanıcı davranışı, etkileşim ve dönüşüm oranları üzerindeki etkilerini görün. Buradaki metriklere ve sonuçlara bakarak akıllıca kararlar alabilir ve uygulamanızın performansını artırabilirsiniz. Eyleme dönüştürülebilir içgörüler bulmak ve uygulamanızın başarısını güçlendirmek için verileri inceleyin. ## A/B testi sonuçları \{#ab-test-results\} Adapty'nin A/B testi sonuçları için sunduğu üç metrik şunlardır: <img src="/assets/shared/img/ab-test-results.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: **Gelir**: Bu metrik, satın almalar ve yenilemelerden USD cinsinden elde edilen toplam tutarı gösterir; kullanıcılara yapılan iade tutarları bu rakamdan düşülür. Hem ilk satın almayı hem de sonraki abonelik yenilemelerini kapsar. Gelir metriği, her A/B testi varyantının finansal performansını değerlendirmenize ve hangisinin en fazla kazanç getirdiğini belirlemenize yardımcı olur. [Paywall](paywall-metrics) metrikleri hakkında daha fazla bilgi edinin. **En iyi olma olasılığı**: Adapty, A/B testi sonuçlarını analiz etmek için sağlam bir matematiksel analiz çerçevesi kullanır ve En iyi olma olasılığı adında bir metrik sunar. Bu metrik, belirli bir varyantın test edilen tüm varyantlar arasında en iyi performansı gösteren seçenek olma olasılığını (uzun vadeli gelir açısından) değerlendirir. Metrik, %1 ile %100 arasında değişen bir yüzde değeri olarak ifade edilir. Adapty'nin bu metriği nasıl hesapladığına dair ayrıntılı bilgi için [dokümantasyona](maths-behind-it) bakabilirsiniz. 1.000 kullanıcı başına gelir açısından en iyi performansı gösteren seçenek yeşil renkte vurgulanır ve otomatik olarak varsayılan seçim olarak belirlenir. **1.000 kullanıcı başına gelir**: 1.000 kullanıcı başına gelir metriği, her A/B testi varyantı için 1.000 kullanıcı başına elde edilen ortalama geliri hesaplar. Bu metrik, toplam kullanıcı sayısından bağımsız olarak varyantlarınızın gelir verimliliğini anlamanıza yardımcı olur. Farklı varyantların performansını standart bir ölçekte karşılaştırmanıza ve gelir üretimi verimliliğine dayalı bilinçli kararlar almanıza olanak tanır. **1.000 kullanıcı başına gelir için tahmin aralıkları**: 1.000 kullanıcı başına gelir metriği aynı zamanda tahmin aralıklarını da içerir. Bu tahmin aralıkları, mevcut veriler ve istatistiksel analize dayanarak belirli bir varyant için 1.000 kullanıcı başına gerçek gelirin düşeceği öngörülen aralığı temsil eder. A/B testi bağlamında, farklı varyantların ürettiği geliri analiz ederken her varyant için 1.000 kullanıcı başına ortalama geliri hesaplıyoruz. Kullanıcılar arasında gelir farklılıkları olabileceğinden, tahmin aralıkları; tahmin süreciyle ilişkili değişkenliği ve belirsizliği göz önünde bulundurarak 1.000 kullanıcı başına düşen gelir için makul değerlere dair net bir gösterge sunar. 1.000 kullanıcı başına gelir metriğine tahmin aralıklarını dahil ederek Adapty, olası gelir sonuçlarının aralığını göz önünde bulundurarak A/B testi varyantlarınızın gelir verimliliğini değerlendirmenizi sağlar. Bu bilgi, tahmin sürecindeki belirsizliği ve 1.000 kullanıcı başına gelir için makul değerleri hesaba katarak veri odaklı kararlar almanıza ve abonelik stratejinizi etkili biçimde optimize etmenize yardımcı olur. Bu metrikler, A/B testi varyantlarınızın finansal performansı, istatistiksel önemi ve gelir verimliliği hakkında bilgi edinmenizi sağlar; böylece veriye dayalı kararlar alabilir ve abonelik stratejinizi daha etkin biçimde optimize edebilirsiniz. ## A/B testi metrikleri \{#ab-test-metrics\} Adapty, paywall veya onboarding varyantlarınız üzerinde yürüttüğünüz A/B testinin performansını etkili biçimde ölçmenize yardımcı olan kapsamlı bir metrik seti sunar. Bu metrikler, görüntülemeler hariç gerçek zamanlı olarak sürekli güncellenir; görüntülemeler ise periyodik olarak güncellenir. Bu metrikleri anlamak, farklı varyantların etkinliğini değerlendirmenize ve paywall veya onboarding stratejinizi optimize etmek için veriye dayalı kararlar almanıza yardımcı olur. A/B testi metrikleri, tüm A/B testlerinizin performansına genel bir bakış sunan A/B testi listesinde mevcuttur. Bu kapsamlı görünüm, her test varyantı için toplu metrikler sunarak performanslarını karşılaştırmanıza ve önemli farklılıkları tespit etmenize olanak tanır. Her A/B testinin daha ayrıntılı analizi için A/B Testi detay metriklerine erişebilirsiniz. Bu bölüm, seçilen A/B testine özgü derinlemesine metrikler sunarak bireysel varyantların performansını incelemenizi sağlar. Görüntülemeler dışındaki tüm metrikler, paywall veya onboarding içindeki ürüne atfedilir. ## Metrik kontrolleri \{#metrics-controls\} Sistem, metrikleri seçilen zaman dilimine göre görüntüler ve üç girinti düzeyi olan sol sütun parametresine göre düzenler. ### Profil kurulum tarihi filtreleme \{#profile-install-date-filtration\} <img src="/assets/shared/img/2bf4d9f-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Metrikleri yükleme tarihine göre filtrele** onay kutusu, metrikleri varsayılan filtreler yerine profil yükleme tarihine göre filtrelemenizi sağlar. Varsayılan filtreler, işlemler için deneme/satın alma tarihini; paywall veya onboarding görüntülemeleri için ise görüntülenme tarihini kullanır. Bu onay kutusunu seçerek, metrikleri profil yükleme tarihiyle hizalayabilir ve belirli bir dönemdeki kullanıcı edinme performansını daha net ölçebilirsiniz. Bu seçenek, metrik analizini kendi ihtiyaçlarınıza göre özelleştirmek için kullanışlıdır. ### Zaman aralıkları \{#time-ranges\} Metrik verilerini analiz etmek için çeşitli zaman dilimlerinden birini seçebilirsiniz; bu sayede günler, haftalar, aylar veya özel tarih aralıkları gibi belirli sürelere odaklanabilirsiniz. <img src="/assets/shared/img/ab-test-time-ranges.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: Adapty, metrik analizini ihtiyaçlarınıza göre özelleştirmek ve filtrelemek için güçlü araçlar sunar. Adapty'nin metrik sayfasında çeşitli zaman aralıklarına, gruplama seçeneklerine ve filtreleme olanaklarına erişebilirsiniz. - ✅ Şuna göre filtrele: Kitle, attribution, ülke, paywall, paywall durumu, paywall grubu, onboarding, placement, ülke, mağaza, ürün ve ürün mağazası. - ✅ Şuna göre grupla: Ürün ve mağaza. :::note A/B testine göre filtrelediğinizde, çapraz placement A/B testleri her placement için ayrı alt testler olarak görünür (örn. `My test child-0`, `My test child-1`). Ayrıntılar için [Çapraz placement A/B testi sınırlamaları](ab-test-types#crossplacement-ab-test-limitations) bölümüne bakın. ::: ## Tekil metrik grafiği \{#single-metrics-chart\} Paywall veya onboarding metrik sayfasının temel bileşenlerinden biri, seçilen metrikleri görsel olarak sunan ve analizleri kolaylaştıran grafik bölümüdür. <img src="/assets/shared/img/e6b0674-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> A/B testi metrik sayfasındaki grafik bölümü, seçilen metrik değerlerini görsel olarak temsil eden yatay bir çubuk grafik içerir. Grafikteki her çubuk bir metrik değere karşılık gelir ve boyutu orantılı olduğundan verileri bir bakışta anlamak kolaylaşır. Yatay çizgi analiz edilen zaman dilimini, dikey sütun ise metriklerin sayısal değerlerini gösterir. Tüm metrik değerlerinin toplam değeri grafiğin yanında görüntülenir. Ayrıca, grafik bölümünün sağ üst köşesindeki ok simgesine tıklamak görünümü genişleterek seçilen metrikleri grafiğin tam satırında gösterir. ## A/B testi özeti \{#ab-test-summary\} Tekli metrik grafiğinin yanında, A/B testinin durumu, süresi, placement'ları ve diğer ilgili ayrıntıları hakkında bilgi içeren A/B testi detay özeti bölümü görüntülenir. <img src="/assets/shared/img/90fa3f5-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Metrik tanımları \{#metrics-definitions\} A/B testleri için kullanılabilen temel metrikler şunlardır: <img src="/assets/shared/img/30c7b68-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Gelir \{#revenue\} Gelir, A/B testinden kaynaklanan satın alma ve yenileme işlemlerinden USD cinsinden elde edilen toplam para miktarını temsil eder. İlk satın alma ve ardından gelen abonelik yenilemelerini kapsar. Gelir metriği, App Store veya Play Store komisyonu düşülmeden önce hesaplanır. [Paywall](paywall-metrics#revenue) gelir metrikleri hakkında daha fazla bilgi edinin. ### Satın almalara dönüşüm oranı (CR to purchases) \{#cr-to-purchases\} Satın almalara dönüşüm oranı, A/B testinizin görüntülemeleri gerçek satın almalara dönüştürmedeki etkinliğini ölçer. Satın alma sayısının görüntüleme sayısına bölünmesiyle hesaplanır. Örneğin 10 satın alma ve 100 görüntüleme varsa satın almalara dönüşüm oranı %10 olur. ### Deneme dönüşüm oranı (CR trials) \{#cr-trials\} Denemelere dönüşüm oranı (CR), A/B testinden başlatılan deneme sayısının görüntüleme sayısına bölünmesiyle elde edilir. Denemelere dönüşüm oranı, A/B testinizin görüntülemeleri deneme aktivasyonlarına dönüştürmedeki etkinliğini ölçer. ### Satın almalar (Purchases) \{#purchases\} Satın almalar metriği, A/B testi sonucunda paywall veya onboarding içinde gerçekleştirilen toplam işlem sayısını temsil eder. Aşağıdaki satın alma türlerini kapsar: - Yeni satın almalar. - Aktive edilen denemelerin satın almaya dönüşmesi. - Aboneliklerin indirgenmesi, yükseltilmesi ve çapraz geçişleri. - Abonelik yenilemeleri (ör. otomatik yenileme olmaksızın süresi dolan bir aboneliğin sonradan yenilenmesi). Yenilemelerin satın almalar metriğine dahil edilmediğini lütfen unutmayın. ### Denemeler (Trials) \{#trials\} Denemeler metriği, A/B testi sonucunda aktive edilen toplam deneme sayısını gösterir. ### İptal edilen denemeler (Trials cancelled) \{#trials-cancelled\} İptal edilen denemeler metriği, otomatik yenilemenin kapatıldığı deneme sayısını temsil eder. Bu durum, kullanıcıların denemeden manuel olarak abonelik iptali yapması sonucunda gerçekleşir. ### İadeler (Refunds) \{#refunds\} A/B testi için iadeler, test edilen varyasyonlarla doğrudan ilişkili iade edilen satın alma ve abonelik sayısını temsil eder. ### Görüntülemeler (Views) \{#views\} Görüntülemeler, A/B testinin kapsadığı paywall veya onboarding'lerin görüntülenme sayısıdır. Kullanıcı iki kez ziyaret ederse bu iki ziyaret olarak sayılır. ### Tekil görüntülemeler (Unique views) \{#unique-views\} Tekil görüntülemeler, paywall veya onboarding'in kaç benzersiz kullanıcı tarafından görüntülendiğini gösterir. Kullanıcı iki kez ziyaret etse bile bu bir tekil görüntüleme olarak sayılır. ### En iyi olma olasılığı (Probability to be the best) \{#probability-to-be-the-best\} En iyi olma olasılığı metriği, bir A/B testindeki belirli bir varyantın test edilen tüm paywall'lar veya onboarding'ler arasında en iyi performans gösteren seçenek olma ihtimalini sayısal olarak ifade eder. Her paywall veya onboarding'in göreli performansını gösteren sayısal bir olasılık sunar. Metrik, %1 ile %100 arasında yüzde değeri olarak ifade edilir. ### ARPU (Kullanıcı başına ortalama gelir) \{#arpu-average-revenue-per-user\} Yalnızca onboarding A/B testleri için. Belirli bir dönemde her kullanıcıdan elde edilen ortalama geliri ölçer. Toplam gelirin benzersiz kullanıcı sayısına bölünmesiyle hesaplanır. ### ARPPU (Ödeme yapan kullanıcı başına ortalama gelir) \{#arppu-average-revenue-per-paying-user\} ARPPU, A/B testi sonucunda ödeme yapan kullanıcı başına ortalama geliri ifade eder. Toplam gelirin benzersiz ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. Örneğin 1.000 ödeme yapan kullanıcıdan 15.000 USD gelir elde ettiyseniz ARPPU 15 USD olur. ### ARPAS (Aktif abone başına ortalama gelir) \{#arpas-average-revenue-per-active-subscriber\} ARPAS, A/B testini yürütmekten elde edilen aktif abone başına ortalama geliri ölçmenizi sağlayan bir metriktir. Toplam gelirin deneme veya abonelik aktive eden abone sayısına bölünmesiyle hesaplanır. Örneğin toplam gelir 5.000 USD ve 1.000 aboneniz varsa ARPAS 5 USD olur. Bu metrik, abone başına ortalama para kazanma potansiyelini değerlendirmeye yardımcı olur. ### Hasılat (Proceeds) \{#proceeds\} A/B testi için hasılat metriği, geçerli App Store / Play Store komisyonu düşüldükten sonra satın almalar ve yenilemelerden uygulama sahibinin USD cinsinden elde ettiği gerçek tutarı temsil eder. Doğrudan uygulamanın kazançlarına katkıda bulunan, A/B testinde denenen varyasyonlarla ilişkili net geliri yansıtır. Hasılatın nasıl hesaplandığına ilişkin daha fazla bilgi için Adapty [dokümantasyonuna](analytics-cohorts#revenue-vs-proceeds) başvurabilirsiniz. ### Tekil aboneler (Unique subscribers) \{#unique-subscribers\} Tekil aboneler metriği, A/B testindeki varyasyonlar aracılığıyla abone olan veya deneme aktive eden farklı bireylerin sayısını temsil eder. Başlattıkları abonelik veya deneme sayısından bağımsız olarak her aboneyi yalnızca bir kez sayar. ### Tekil ödeme yapan aboneler (Unique paid subscribers) \{#unique-paid-subscribers\} Tekil ödeme yapan aboneler metriği, A/B testindeki varyasyonlar aracılığıyla bir satın alma işlemini başarıyla tamamlayarak ödeme yapan abone haline gelen benzersiz kişi sayısını temsil eder. ### İade oranı (Refund rate) \{#refund-rate\} A/B testi için iade oranı, testteki varyasyonlarla doğrudan ilişkili iade sayısının ilk kez yapılan satın alma sayısına (yenilemeler hariç) bölünmesiyle hesaplanır. Örneğin 5 iade ve 1.000 ilk kez satın alma varsa iade oranı %0,5 olur. ### Tekil satın alma dönüşüm oranı (Unique CR purchases) \{#unique-cr-purchases\} A/B testi için tekil satın alma dönüşüm oranı, testteki varyasyonlarla ilişkili satın alma sayısının tekil görüntüleme sayısına bölünmesiyle hesaplanır. Örneğin 10 satın alma ve 100 tekil görüntüleme varsa tekil satın alma dönüşüm oranı %10 olur. ### Tekil deneme dönüşüm oranı (Unique CR trials) \{#unique-cr-trials\} A/B testi için tekil deneme dönüşüm oranı, testteki varyasyonlarla ilişkili başlatılan deneme sayısının tekil görüntüleme sayısına bölünmesiyle hesaplanır. Örneğin 30 başlatılan deneme ve 100 tekil görüntüleme varsa tekil deneme dönüşüm oranı %30 olur. ### Tamamlamalar ve tekil tamamlamalar (Completions & unique completions) \{#completions--unique-completions\} Yalnızca onboarding A/B testleri için. Tamamlamalar, kullanıcıların A/B testindeki varyasyonlar aracılığıyla onboarding'i tamamlama (yani ilk ekrandan son ekrana geçme) sayısını sayar. Biri iki kez tamamlarsa bu iki **tamamlama** ancak bir **tekil tamamlama** sayılır. ### Tekil tamamlama oranı (Unique completions rate) \{#unique-completions-rate\} Yalnızca onboarding A/B testleri için. Tekil tamamlama sayısının tekil görüntüleme sayısına bölünmesiyle elde edilir. Bu metrik, insanların A/B testindeki varyasyonlar aracılığıyla onboarding ile nasıl etkileşime girdiğini anlamanıza ve onboarding'in görmezden gelindiğini fark ettiğinizde değişiklik yapmanıza yardımcı olur. --- # File: maths-behind-it --- --- title: "A/B testlerinin arkasındaki matematik" description: "Daha iyi gelir analizleri için abonelik analitiğinin arkasındaki matematiği anlayın." --- A/B testi, bir flow, paywall veya onboarding'in iki farklı versiyonunun performansını karşılaştırmak için kullanılan güçlü bir tekniktir. Temel amaç, 12 aylık dönemde kullanıcı başına ortalama gelire dayanarak hangi versiyonun daha etkili olduğunu belirlemektir. Ancak veri toplamak ve karar vermek için tam bir yıl beklemek pratik değildir. Bu nedenle, hedef metriği yaklaşık olarak temsil etmek amacıyla geçmiş veri analizine dayanan bir vekil metrik olarak kullanıcı başına 2 haftalık gelir kullanılmaktadır. Doğru ve güvenilir sonuçlar elde etmek için farklı veri türlerini işleyebilen sağlam bir istatistiksel yöntem kullanmak kritik önem taşır. Modern veri analizinde popüler bir yaklaşım olan Bayesci istatistik, A/B testi için esnek ve sezgisel bir çerçeve sunar. Bayesci yöntemler, önceki bilgiyi dahil ederek yeni verilerle güncellemek suretiyle belirsizlik altında daha iyi kararlar alınmasına olanak tanır. Bu belge, Adapty'nin A/B testi sonuçlarını değerlendirmede ve veri odaklı karar alma süreçlerine değerli içgörüler sunmada kullandığı matematiksel analize kapsamlı bir rehber niteliği taşımaktadır. ## Adapty'nin istatistiksel analiz yaklaşımı \{#adaptys-approach-to-statistical-analysis\} Adapty, A/B testlerinin performansını değerlendirmek ve doğru, güvenilir içgörüler sunmak için kapsamlı bir istatistiksel analiz yaklaşımı benimser. Metodolojimiz şu temel adımlardan oluşur: 1. **Metrik tanımı:** Bir A/B testini başarıyla yürütmek için analizin belirli hedef ve amaçlarıyla örtüşen temel metriği tanımlamanız gerekir. Adapty, 1 yıl sonraki ortalama gelir şeklindeki uzun vadeli hedef için hangi metriğin proxy görevi üstlendiğini belirlemek amacıyla büyük miktarda abonelik uygulaması tarihsel verisinden yararlandı; bu metrik 14 günlük ARPU olarak belirlendi. 2. **Hipotez oluşturma:** A/B testi için iki hipotez oluşturuyoruz. Sıfır hipotezi (H0), kontrol grubu (A) ile test grubu (B) arasında anlamlı bir fark olmadığını varsayar. Alternatif hipotez (H1), iki veya daha fazla grup arasında anlamlı bir fark bulunduğunu öne sürer. 3. **Dağılım seçimi:** Verinin özelliklerine ve gözlemlediğimiz metriğe göre en uygun dağılım ailesini seçiyoruz. Buradaki en yaygın tercih, sıfır değerleri de göz önünde bulundurularak log-normal dağılımıdır. 4. **En iyi olma olasılığı hesabı:** Bayesci A/B testi yaklaşımını kullanarak, teste katılan her paywall veya onboarding varyantı için en iyi seçenek olma olasılığını hesaplıyoruz. Bu değer daha önce kullandığımız p-değerleriyle ilişkilidir; ancak özünde farklı, daha sağlam ve anlaşılması daha kolay bir yaklaşımdır. 5. **Sonuçların yorumlanması:** En iyi olma olasılığı tam olarak adından anlaşıldığı gibidir. Olasılık ne kadar yüksekse, belirli bir seçeneğin iş için en iyi tercih olma ihtimali o kadar artar. Karar alma eşiğini kendiniz belirlemeniz gerekir; bu eşik, durumunuza özgü pek çok faktöre bağlı olmalıdır. Yaygın bir olasılık eşiği ise %95'tir. 6. **Tahmin aralıkları:** Adapty, her grup için performans metriklerine ilişkin tahmin aralıkları hesaplar ve gerçek popülasyon parametresinin büyük olasılıkla düşeceği bir değer aralığı sunar. Bu, tahmini performans metrikleriyle ilişkili belirsizliği ölçümlendirmeye yardımcı olur. ## Örneklem büyüklüğünün belirlenmesi \{#sample-size-determination\} Güvenilir ve kesin A/B testi sonuçları için uygun bir örneklem büyüklüğü belirlemek kritik öneme sahiptir. Adapty, yeterli bir örneklem büyüklüğünü sağlamak amacıyla Bayesci yaklaşım altında da önemini koruyan istatistiksel güç ve beklenen etki büyüklüğü gibi faktörleri göz önünde bulundurur. Şu anda kullandığımız Bayesci yaklaşıma özgü gerekli örneklem büyüklüğünü tahmin etme yöntemleri, analizin güvenilirliğini güvence altına alır. A/B testlerinin işlevselliği hakkında daha fazla bilgi edinmek için [A/B testi oluşturma](ab-tests) ve [A/B testi çalıştırma](run_stop_ab_tests) belgelerimize, ayrıca çeşitli [A/B testi metrikleri ve sonuçlarına](results-and-metrics) ilişkin kaynaklarımıza başvurmanızı öneririz. Adapty'nin A/B testlerine yönelik analitik çerçevesi artık Bayesci bir yaklaşım benimsemektedir; ancak odak noktası yine metriklerin tanımlanması, hipotezlerin oluşturulması ve dağılımların seçilmesi üzerindedir. Artık p-değerleri hesaplamak yerine, posterior dağılımları hesaplıyor ve her varyantın en iyi olma olasılığını belirliyoruz. Ayrıca tahmin aralıklarını da hesaplıyoruz. Bu güncellenmiş yaklaşım, kapsamlı ve daha da sağlam olmayı sürdürürken, daha sezgisel ve yorumlaması daha kolay içgörüler sunmak üzere tasarlanmıştır. Amaç, işletmelere A/B testlerinin sağlam istatistiksel analizine dayalı olarak stratejilerini optimize etme, performansı iyileştirme ve büyümeyi destekleme konularında güç kazandırmak olmaya devam etmektedir. --- # File: autopilot-how-it-works --- --- title: "AI Büyüme Danışmanı: Nasıl çalışır?" description: "AI Büyüme Danışmanı'nın arkasındaki mantığı anlayın ve gelirinizi artırmak için bize güvenin." --- [AI Growth Advisor](autopilot), gerçek performans verilerinize ve pazarınızdaki benzer uygulamaların nasıl performans gösterdiğine dayanarak hangi deneyleri çalıştırmanız gerektiğini belirlemenize yardımcı olur. Neyin işe yarayabileceğini tahmin etmek yerine, sonuçlarınızı iyileştirme olasılığı daha yüksek olan testler için spesifik öneriler alırsınız. Bu makale, AI Growth Advisor'ın nasıl düşündüğüne şeffaf bir bakış sunuyor — hangi verileri kullandığını, fırsatları nasıl değerlendirdiğini ve neden belirli önerilerin ortaya çıktığını açıklıyor. Amaç, onu büyüme iş akışınızın bir parçası olarak kullanırken güvenle yararlanmanızı sağlamaktır. ## AI Growth Advisor aslında ne yapar \{#what-ai-growth-advisor-actually-does\} AI Growth Advisor, gelirinizi artırma ihtimali en yüksek deneyleri bulmak için uygulamanızın ve paywall metriklerinizin analizini yapar. Şunlara bakar: - **Mevcut kurulumunuz**: fiyatlandırma, denemeler, ürünler ve bunların ne kadar iyi dönüştüğü - **Pazar örüntüleri**: benzer uygulamaların tekliflerini nasıl yapılandırdığı ve ne kadar ücret talep ettiği - **Test geçmişiniz**: hangi deneyleri zaten çalıştırdığınız ve bunların neler ortaya koyduğu - **Büyüme potansiyeli**: hangi değişikliklerin fark yaratma ihtimalinin en yüksek olduğu Growth Advisor, tüm bu faktörleri birlikte değerlendirmek ve hemen başlatabileceğiniz A/B testlerine dönüştürmek için yapay zekâdan yararlanır. Rakip araştırması yapmadan veya sırada ne test edeceğinizi tahmin etmeden hazır bir plan elde edersiniz. ## AI Büyüme Danışmanı'nın arkasındaki veriler \{#the-data-behind-ai-growth-advisor\} Her öneri, birlikte çalışan üç ana veri kaynağından oluşturulur. #### Uygulamanızın kendi verileri \{#your-apps-own-data\} AI Büyüme Danışmanı, uygulamanızın bugünkü performansına bakar: - Paywalllarınızdaki dönüşüm metrikleri - Fiyatlandırma ve ürün yapısı Bu, AI Büyüme Danışmanı'na herhangi bir değişiklik önermeden önce üzerinden çalışabileceği bir temel sağlar. :::note Uygulamanızın performans verilerini diğer uygulamalar için öneri eğitiminde kullanmıyoruz. Verileriniz gizli kalır. ::: #### Paywall analizi \{#paywall-analysis\} AI Growth Advisor, ödeme ekranınızın ekran görüntüsünü analiz eder ve tasarımını, kategorinizdeki en iyi performans gösteren uygulamaların kullandığı yerleşik kalıplarla karşılaştırır. Yerleşim seçeneklerini, metni, abonelik dökümanlarını ve tasarruf rozetleri veya inceleme bölümleri gibi dönüşüm odaklı unsurları değerlendirir. Bu analiz iki tür öneri üretir: - **Kıyaslama tabanlı öneriler** — en iyi performans gösteren uygulamaların neler yaptığına dayanır ve her biri somut bir istatistikle desteklenir (örneğin, "En iyi performans gösteren Eğitim uygulamalarının %72'si tarafından kullanılıyor"). - **Görsel analiz önerileri** — yapay zeka tarafından ekran görüntünüzden üretilir; metin iyileştirmeleri, düzen değişiklikleri ve diğer tasarım ayarlamalarını kapsar. Bu öneriler, [büyüme planınıza](autopilot-growth-plan#view-the-growth-plan) doğrudan hipotez olarak aktarılır ve [A/B testi olarak başlatabilirsiniz](autopilot-execute-plan). #### Rakip verileri \{#competitor-data\} AI Growth Advisor, fiyatlandırma, abonelik yapıları ve kategorinizdeki yaygın kalıplar gibi genel bilgileri kullanarak kurulumunuzu pazarınızdaki benzer uygulamalarla karşılaştırır. Rakip fiyatlandırması ve yapıları pazardan pazara farklılık gösterdiğinden, bu karşılaştırmalar ülkeye özeldir. Rakip fiyatlandırması, metrik analizinde kullanılan anonimleştirilmiş Adapty ağı verilerinden farklı olarak App Store gibi üçüncü taraf ve kamuya açık kaynaklardan alınır. Bu şekilde, rastgele fikirler yerine sizinle aynı kategorideki uygulamalarda zaten işe yarayan stratejileri test ediyorsunuz. Analizi gördüğünüzde, kendi metriklerinizi ve rakip fiyatlarını yan yana karşılaştırabilirsiniz. Benzer uygulamalar farklı bir fiyatlandırma veya yapıyla daha iyi sonuç alıyorsa, aynı yaklaşımın sizin için de işe yarayabileceğinin güçlü bir işareti. :::tip AI Growth Advisor, gerçekçi biçimde rekabet edebileceğiniz uygulamalara göre ilgili rakipleri otomatik olarak seçer. Genel olarak bu önerilere bağlı kalmanızı tavsiye ederiz; çok ileride ya da çok geride olan uygulamaları listeye eklemeyin. Uygulamanız birden fazla kategoriye giriyorsa, en ilgili pazar segmentine odaklanmak için listeyi düzenlemek isteyebilirsiniz. ::: #### Sektör kıyaslamaları \{#industry-benchmarks\} AI Growth Advisor, belirli bir ülkedeki kategori ortalamasıyla nasıl karşılaştırıldığınızı göstermek için Adapty tarafından takip edilen 20.000 abonelik uygulamasından elde edilen anonimleştirilmiş verileri kullanır. Veriler ağ genelinde toplanır ve hiçbir zaman belirli bir uygulamaya bağlanmaz. Örneğin, dönüşüm huniniz ve yükleme başına geliriniz, kategorinizdeki ve ülkenizdeki uygulamaların ortalamasıyla karşılaştırılır. Bu sayede ortalamanın altında mı, ortalama düzeyde mi yoksa önde mi olduğunuzu görebilirsiniz. #### Coğrafi pazar verileri \{#geographic-market-data\} AI Growth Advisor, bireysel coğrafi pazarları analiz eder — 20.000 uygulamalık Adapty ağındaki örüntülerden yararlanarak — bölgesel fiyat ayarlamalarının daha fazla gelir sağlayabileceği yerleri tespit eder. Her ülke için şunları değerlendirir: - **Dönüşüm oranı**: Yüklemeden ödemeye geçiş oranının küresel ortalama ile karşılaştırması. Daha yüksek bir oran fiyatları artırmaya alan olduğuna işaret edebilir; daha düşük bir oran ise fiyat hassasiyetine işaret edebilir. - **Fiyat endeksi**: Ülkenin, halkın satın alma gücünü gösteren [Adapty Fiyat Endeksi](https://uploads.adapty.io/adapty_pricing_index.pdf)'ndeki konumu. [coğrafi fiyatlandırma önerilerinden](autopilot-growth-plan#geo-pricing-hypotheses) büyüme planınızdaki A/B testleri oluşturarak bu tavsiyelere göre harekete geçebilirsiniz. ## AI Growth Advisor'ın önerileri nasıl belirlediği \{#how-ai-growth-advisor-decides-what-to-recommend\} AI Growth Advisor, paywall dönüşümünüzü artırmak için bir öneri havuzu oluşturur. Bu öneriler, her değişikliğin etkisini güvenilir biçimde ölçebilmek amacıyla birer birer test edilecek şekilde tasarlanmıştır. AI Growth Advisor'ın önerileri nasıl oluşturduğu aşağıda açıklanmıştır: 1. **En büyük fırsatları bul** AI Growth Advisor, fiyatlandırmanızı, ürünlerinizi ve dönüşüm hunisi performansınızı inceleyerek bunları sektör kalıpları ve benzer uygulamalarla karşılaştırır. Analiz, yalnızca USD değil, birincil pazarınızın para biriminde çalışır; böylece fiyat önerileri, abonelerinizin gerçekten ödediği tutarlara uygun olur. Fiyatı ayarlamak, deneme süresi eklemek veya teklif yapısını değiştirmek gibi en fazla iyileştirme yapabileceğiniz noktaları belirler. 2. **Sonraki deneyi seçin** Her hipotez, mevcut test geçmişinize dayanılarak oluşturulur. AI Growth Advisor, hangi deneyleri zaten yürüttüğünüzü, hangilerinin kazandığını ve hangi yönlerin hâlâ keşfedilmeye değer olduğunu bilir. Bir sonraki öneri, belirli bir sırayı takip etmek yerine bir öncekinin ortaya çıkardıkları üzerine inşa edilir. 3. **Kazanan ile rakip arasında testler yürütün** Her deneyden sonra kazanan yeni temeliniz olur. Bu sonuç, büyüme planınızdaki bir sonraki öneriyi şekillendirir — AI Growth Advisor işe yarayanları korur, işe yaramayanları eler ve oradan bir sonraki testi seçer. 4. **Pratik tutun** AI Growth Advisor yalnızca mevcut ürün ve kurulumunuzla ya da yeni bir ürün oluşturmak veya fiyatı değiştirmek gibi küçük değişikliklerle hayata geçirebileceğiniz testler önerir. Amaç, testleri hızlı ve yönetilebilir tutmaktır. 5. **Size gerekçeyi gösterir** Her öneri için AI Growth Advisor, bu testin neden çalıştırmaya değer olduğunu tam olarak açıklayan net bir hipotez sunar. Mevcut metriklerinizin rakipler ve sektör ortalamaları ile nasıl karşılaştırıldığını, fırsatın ne olduğunu ve hangi temel metriklerin iyileşmesini beklediğimizi göreceksiniz. Bu, her testin size bir şeyler öğrettiği ve sizi daha etkili bir paywall'a doğru götürdüğü tekrarlanabilir bir deneyim sürecine dönüştürür. ## Her deneyin ardından ne olur \{#what-happens-after-each-experiment\} Öneriler tükenmez. Tamamlanan her test, yeni deneylerin temeli haline gelir. Test etmeye devam ettiğiniz sürece AI Growth Advisor, sırada ne denemeniz gerektiğini önermeyi sürdürür. Temel piyasa verilerini yenilemek için aynı placement üzerinde analizi yeniden çalıştırın. Her yeni çalıştırma; güncel rakip fiyatlandırmasını, dönüşüm kıyaslamalarını ve kategori trendlerini çeker; yeni tespit edilen hipotezleri mevcut büyüme planınıza ekler, var olanları değiştirmez. Yapay zeka tarafından oluşturulan mevcut hipotezleriniz, özel hipotezleriniz ve devam eden A/B testleriniz yeniden çalıştırmalar boyunca korunur. Temel çizginizi optimize ettikten sonra, daha gelişmiş rakipler karşısında da rekabet etmeyi tercih edebilirsiniz. Bu yinelemeli yaklaşım, uygulamanız büyüdükçe ve pazar değiştikçe gelirinizi en üst düzeye çıkarmanıza yardımcı olur. :::tip Denemek ister misiniz? Paywalllarınızı analiz etmek ve A/B testleri içeren bir büyüme planı oluşturmak için [AI Growth Advisor](autopilot-analysis)'ı başlatın. Karmaşık testleri sorunsuzca başlatmak için [yerleşik sihirbazı](autopilot-execute-plan) kullanın: ürün oluşturma, paywall kopyalama ve segment kurulumu süreçlerinde size rehberlik edecektir. ::: --- # File: autopilot-analysis --- --- title: "Paywall ve Pazar Analizi" description: "Uygulamanıza özel, veriye dayalı bir büyüme planı oluşturun." --- AI Growth Advisor analizini çalıştırmak ve bir büyüme planı oluşturmak için bu makaledeki adımları izleyin. Hedef placement için daha önce bir büyüme planı oluştturduysanız, bu analiz aralarından seçim yapabileceğiniz yeni hipotezler üretecektir. :::tip Başlamadan önce [analize ilişkin gereksinimleri](autopilot#prerequisites) karşıladığınızdan emin olun. ::: ## Paywall Analizi \{#paywall-analysis\} ### Analiz için bir paywall seçin \{#select-a-paywall-for-analysis\} 1. **AI Growth Advisor** sayfasını açın ve [Get Growth plan](https://app.adapty.io/ab-tests/analysis/start) düğmesine tıklayın. 2. **Paywall Diagnostic** sayfasında, açılır menülerden bir **Placement** ve **Paywall** seçin. Adapty, en yüksek gelirli placement'ı ve ona ait en iyi paywall'u otomatik olarak önceden seçer. Farklı bir paywall analiz etmek için önce placement'ı değiştirin. 3. Bir ekran görüntüsü yükleyin. AI Growth Advisor, paywall tasarımınızı ve içeriğinizi analiz etmek için bir ekran görüntüsüne ihtiyaç duyar. 4. Paywall'ın aktif ürünlerini inceleyin. Sağdaki ürün kartları, her ürünün abonelik süresini, fiyatını ve deneme süresini gösterir. 5. Devam etmek için **Confirm & Analyze** düğmesine tıklayın. Adapty, paywall'ınızı analiz eder ve tanılama raporunu görüntüler. ### Paywall analiz raporu \{#paywall-analysis-report\} Bir paywall seçip ekran görüntüsü yükledikten sonra Adapty, paywallınızı yerleşik tasarım kalıpları açısından analiz ederek hem iyi tercihleri hem de iyileştirme fırsatlarını öne çıkarır. #### Neler iyi çalışıyor \{#whats-working-well\} Bu bölüm, dönüşümü en üst düzeye çıkaran yerleşik kalıpları nasıl kullandığınızı vurgular. Örneğin: görünür bir tasarruf rozeti, öne çıkan bir kullanıcı yorumu bölümü veya açık abonelik özeti. #### Paywallınızda düzeltilmesi gerekenler \{#what-to-fix-on-your-paywall\} Adapty önerilerini iki kategoriye ayırır: - **Kıyaslamalı öneriler**: Kategorinizdeki en başarılı uygulamaları temel alan, veriye dayalı öneriler. Her öneri bir kıyaslama istatistiği (örneğin, "En başarılı Eğitim uygulamalarının %72'si tarafından kullanılıyor") ve neyi değiştireceğinize dair bir açıklama içerir. - **Görsel analiz önerileri**: Paywall ekran görüntünüzü temel alan, yapay zeka tarafından üretilen öneriler. Bunlar; metin iyileştirmeleri, düzen değişiklikleri ve daha fazlasını içerir. :::tip [Büyüme planınız](autopilot-growth-plan#view-the-growth-plan), kıyaslanmış önerilere dayalı hipotezler içerecektir. Görsel analiz önerilerini plana manuel olarak ekleyebilirsiniz. ::: Devam etmek için **Get Market Insights** düğmesine tıklayın. ## Pazar ve Rakip Analizi \{#market-and-competitor-analysis\} :::note Pazar ve rakip analizi, önce [paywall analizinin](#paywall-analysis) tamamlanmasını gerektirir. ::: Market Insights analizi, uygulamanızın fiyatlandırma ve dönüşüm metriklerini rakipleriyle ve sektör ortalamasıyla karşılaştırır. Karşılaştırmalar ülkeye özgüdür. Adapty, bir kıyaslama noktası sağlamak için App Store'daki uygulamalardan elde edilen verileri alt kategorinize ve ülkenize göre toplar ve analiz eder. Bu veriler başka hiçbir yerde kamuya açık değildir. ### Rakipleri Seçin \{#select-competitors\} Karşılaştırma için en fazla 5 rakip seçin. Adapty otomatik olarak 5 rakip belirler ve 5 tane daha önerir. App Store bağlantısıyla uygulamaları manuel olarak da ekleyebilirsiniz. Daha iyi sonuçlar için sizden daha yüksek MRR'ye sahip uygulamaları seçin. Listeyi onaylamak için **Generate report** düğmesine tıklayın ve analizin tamamlanmasını bekleyin. ### Ülke Seçin \{#select-a-country\} Ayrıntılı analiz için en iyi ülkelerinizden birini seçmek amacıyla Ülke açılır menüsünü kullanın. ### Gelir dağılımı \{#revenue-distribution\} Bu gelir dağılımı grafiği, gelirinizin hangi ülkelerden geldiğini yüzdelik dağılımlarla gösterir. Analizin geri kalanında odaklanılan ilk 5 ülkenizi öne çıkarır. ### Rakip fiyatlandırma \{#competitor-pricing\} Rakip fiyatlandırma tablosu, paywall'ınızın abonelik fiyatlarını [seçilen ülkedeki](#select-a-country) rakiplerinizin fiyatlarıyla karşılaştırır. Her abonelik süresi için ayrı sütunlar içerir. ### Dönüşüm hunisi \{#conversion-funnel\} Bu grafik, dönüşüm oranlarınızı — Görüntülemeden Denemeye, Denemeden Ödemeye ve Görüntülemeden Ödemeye — benzer uygulamaların ortalamasıyla yan yana gösterir. ### Süreye göre gelir dağılımı \{#revenue-distribution-by-duration\} Bu grafik, hangi abonelik sürelerinin gelirinize en fazla katkıda bulunduğunu sektör ortalamasıyla karşılaştırarak gösterir. Geliriniz belirli bir süreye yoğun biçimde yönelmişse, bu durum fiyatlandırma stratejinizi optimize etmek için bir fırsat olduğuna işaret edebilir. ### Aktivasyon ARPU \{#activation-arpu\} **Aktivasyon ARPU: uygulamanız ve kategori** grafiği, uygulamanızın yeni kurulum başına ortalama gelirini kategori ortalamasıyla karşılaştırır. Bunu [dönüşüm hunisiyle](#conversion-funnel) birlikte kullanın: - Dönüşüm, kaç kullanıcının ödeme yaptığını gösterir. - Aktivasyon ARPU ise kullanıcı başına ortalama geliri gösterir. Yüksek bir dönüşüm oranıyla birlikte düşük bir Aktivasyon ARPU, tekliflerin düşük fiyatlandırıldığına işaret edebilir. Bu metrik **kohort tabanlıdır**. Adapty, son 90 günde uygulamayı yükleyen kullanıcıları alır ve bu kullanıcıların elde ettiği geliri kullanıcı sayısına böler. #### Diğer metriklerle karşılaştırma \{#comparison-to-other-metrics\} Aktivasyon ARPU, kontrol panelinizde başka yerlerde gördüğünüz ARPU değerleriyle eşleşmeyecektir — her metrik farklı bir şeyi ölçer. - **[ARPU analitik grafiği](arpu)**: Eski kohortların yenilemelerini de içerir; bu nedenle değer, Aktivasyon ARPU'sundan birkaç kat daha yüksektir. - **[Gelir grafiği](revenue), Dönem filtresi "Activation" olarak ayarlandığında**: Yalnızca her kullanıcının ilk ödemesini sayar. Kohortun 90 günlük pencere içinde yaptığı yenilemeleri saymaz. - **[Kohort geliri](analytics-cohorts) (90 gün)**: En yakın eşdeğer — bu metriği referans olarak kullanın. ## Sonraki Adımlar \{#next-steps\} Analiz sonuçlarına göre A/B testlerini nasıl yürüteceğinizi öğrenmek için [Büyüme planınızı yönetin ve uygulayın](autopilot-growth-plan) makalesini okuyun. Analiz sonuçlarınızı dilediğiniz zaman Growth Plan sayfasından görüntüleyebilirsiniz. Bunun için **Analysis Results** sekmesine tıklamanız yeterli. --- # File: autopilot-growth-plan --- --- title: "Büyüme planınızı yönetin" description: "Özel hipotezler ekleyin, arşivleyin ve büyüme planını güncelleyin." --- [Analizi](autopilot-analysis) tamamladıktan sonra Adapty, büyüme planınızı sunar — **uygulanabilir iyileştirme hipotezlerinden** oluşan bir liste. Her öğe, yeni bir fiyat noktası veya tasarım iyileştirmesi önerir. Bir hipotez açın ve [bunu bir A/B testi ile deneyin](autopilot-execute-plan). Her placement'ın kendi büyüme planı vardır. Piyasa koşulları değiştikçe önerileri güncellemek için analizi yeniden çalıştırabilirsiniz. Geçmiş çalıştırmalar sürüm geçmişinde saklanır. ## Hipotezler \{#hypotheses\} Hipotezleri türe göre filtrelemek için büyüme planının en üstündeki sekmeler arasında geçiş yapın: - **En yüksek öncelik**, en fazla etki yaratabilecek hipotezleri içerir. Uygun hipotez yoksa bu sekme gizlenir. - **Tümü**, aktif planınızdaki tüm hipotezleri gösterir. - **Fiyatlandırma** hipotezleri, yeni fiyat noktalarını veya deneme süresi yapılandırmalarını inceler. Her biri, paywall tanısından veya pazar içgörüleri raporundan gelen belirli bir öneriye dayanır. - **Görsel** hipotezler, tasarım iyileştirme önerilerdir. Metin, düzen veya diğer görsel öğelerdeki değişiklikleri kapsayabilir. - [**Coğrafi fiyatlandırma**](#geo-pricing-hypotheses) hipotezleri, ülkeye özgü fiyat ayarlamalarını test eder. - [**Arşivlenen**](#archive-a-hypothesis) hipotezler, aktif planınızdan kaldırdığınız önerilerdir. İstediğiniz zaman geri yükleyebilirsiniz. Kendi [hipotezinizi ekleyebilir](#add-your-own-hypothesis) ya da test etmek istemediğiniz hipotezleri [arşivleyebilirsiniz](#archive-a-hypothesis). Bu hipotezleri herhangi bir sırayla, birer birer test edin. Coğrafi fiyatlandırma testleri bunun istisnasıdır; kitleleri örtüşmediğinden paralel olarak çalıştırılabilirler. ### Coğrafi fiyatlandırma hipotezleri \{#geo-pricing-hypotheses\} :::important Tek seferlik satın almalar, bölgesel fiyat optimizasyonu için uygun değildir. ::: Coğrafi fiyatlandırma önerilerinin listesini görmek için **Geo-pricing** sekmesini açın. Her öneri, tek bir fiyat değişikliğiyle bir ülkeyi hedefler ve ayrı bir A/B testi olarak çalışır. Adapty, fiyat ayarlaması gerektiren ülkeleri tespit eder ve [Adapty Pricing Index](https://uploads.adapty.io/adapty_pricing_index.pdf) tarafından doğrulanmış veri odaklı öneriler sunar. <br /> #### Adapty'nin coğrafi fiyatlandırma önerileri nasıl oluşturulur \{#how-adapty-makes-geo-pricing-suggestions\} - Fiyatlandırma önerileri App Store verilerine dayanır. Oluşturulan A/B testi hem App Store hem de Google Play'de çalıştırılabilir. - Fiyat değişim yüzdesi tüm abonelik sürelerinde aynıdır. - Tüm fiyatlar en yakın App Store fiyat kademesine yuvarlanır. - Adapty'nin o ülkeye ait işlem verisi varsa fiyatlar yerel para biriminde (örneğin EUR veya GBP) gösterilir. Yerel veri yoksa fiyatlar USD olarak gösterilir. ### Hipotez durum rozetleri \{#hypothesis-status-badges\} 1. **Şimşek simgesi** — en yüksek öncelikli önerileri gösterir. 2. **Ürün senkronizasyon durumu** — A/B testini başlatmak için bir ürün eylemi gerektiğinde görünür. - **Draft** — ürün kurulumu tamamlanmamış (Adapty tarafı) - **Action required** — ürün kurulumu tamamlanmamış (Mağaza tarafı) - **Pending...** — Adapty, mağazanın incelemeyi veya ilk senkronizasyonu tamamlamasını bekliyor. - **Approved** — ürün mağaza tarafından onaylanmış ve test için hazır. - **Rejected** — mağaza ürünü reddetti. - **Not connected** — ürün henüz mağazaya bağlı değil. 3. **A/B testi durumu** — A/B testini başlattığınızda görünür: - **Draft test** — test taslak olarak kaydedilmiş ancak henüz çalışmıyor. - **Running** — test yayında. - **Completed** — test tamamlandı. - **Archived test** — test sonuçlandırılmadan arşivlendi. ## Yapay zeka tarafından oluşturulan yeni hipotezler alma \{#get-new-ai-generated-hypotheses\} Her testin ardından Adapty, sonuca göre hipotezlerinizi otomatik olarak günceller. Güncel rakip fiyatlandırması, dönüşüm kıyaslamaları ve kategori trendlerini çekmek için büyüme planı başlığındaki **Update** Refresh düğmesine tıklayın — ya da AI Growth Advisor ana sayfasındaki **Update Analysis** seçeneğine tıklayın. İstendiğinde **Get New Ideas**'a tıklayın. Adapty, placement'ınız önceden seçili olarak analiz sihirbazını açar. Paywall analizi ve rakip araştırması tekrarlanır; Adapty, sonuçlardan yeni hipotezler belirler. İstediğiniz hipotezleri seçin ya da hepsini kabul etmek için **Add All To Plan** Plus düğmesine tıklayın. Yeni eklenen hipotezler listenin en üstünde görünür. Mevcut yapay zeka tarafından oluşturulan hipotezleriniz, özel hipotezleriniz ve devam eden A/B testleriniz bundan etkilenmez. Bir güncellemeyi tamamlamadan çıkarsanız, devam etmek için **devam ettir** seçeneğini veya baştan başlamak için **iptal et** seçeneğini kullanabilirsiniz. ## Kendi hipotezinizi ekleyin \{#add-your-own-hypothesis\} Kendi fiyatlandırma veya görsel önerinizi oluşturmak için **Add Hypothesis** Plus düğmesine tıklayın. Formu doldurun: başlık, açıklama ve hipotez türü (**Monetization** veya **Visual**). - İyileştirmeyi hedeflediğiniz metrikleri açılır menüden seçin. - Monetization hipotezleri için ayrıca test ürünlerini de seçmeniz gerekir. ## Bir hipotezi arşivleme \{#archive-a-hypothesis\} Bir hipotezi arşivlemek için Close düğmesine tıklayın, ardından onaylamak için Skip'e tıklayın. İsteğe bağlı olarak nedenini açıklayabilirsiniz — bu, Adapty'nin gelecekteki önerilerini geliştirmesine yardımcı olur. Hipotez **Archived** sekmesine taşınır. Arşivlenmiş bir hipotezi aktif planınıza geri yüklemek için karttaki **Restore** düğmesine tıklayın. ## Eski hipotezleri yeniden inceleyin ve kullanın \{#revisit-and-reuse-old-hypotheses\} Geçmiş analizlerde oluşturulan önerilere göz atmak için büyüme planı başlığındaki **Clock** Clock simgesine tıklayın. **Version history** modalı, söz konusu placement için geçmişteki tüm çalıştırmaları listeler — tarih, paywall ve o sırada kaç hipotezi kabul ettiğiniz. Geçmiş bir çalıştırmaya tıklayarak ürettiği hipotezleri görüntüleyebilirsiniz. **Add to Plan** Plus seçeneğiyle herhangi birini aktif planınıza ekleyebilirsiniz — ilk seferinde uygulamadığınız önerileri tekrar değerlendirmek için kullanışlıdır. --- # File: autopilot-execute-plan --- --- title: "Büyüme planınızı hayata geçirin" description: "Büyüme planı hipotezlerinizden A/B testleri başlatın." --- Testleri herhangi bir sırada çalıştırabilirsiniz, ancak **tek tek** çalıştırmanız gerekir. Coğrafi fiyatlandırma testlerinin kitleleri çakışmadığından, bu testler birbirine paralel olarak çalıştırılabilir. Bir test sona erdiğinde, kazanan stratejiyi bir sonraki tura taşıyın. Her tur, uygulamanız için daha verimli bir kuruluma doğru ilerler. Tahminlerimize göre, önerilen testlerin tamamını çalıştırmak gelirinizi **%80'e kadar artırabilir**. :::important Her öneri, A/B testi için minimum süreyi içerir. Bir sonraki aşamaya geçmeden önce en doğru verileri elde etmek için bu önerilere uyun. A/B testini manuel olarak durdurmanız gerekecektir. ::: Bir hipotez açın ve A/B testi oluşturma sihirbazını başlatmak için **Set Up & Run Test** düğmesine tıklayın. ## Adım 1: Hipotezi görüntüleyin \{#step-1-view-the-hypothesis\} İlk adım, hipoteze genel bir bakış sunar. Önerilen değişiklikleri özetler ve bunların gerekçesini açıklar. Bir sonraki adıma geçmek için "Set up & Run Test" seçeneğine tıklayın. {/* TODO: REPLACE SCREENSHOT */} ## Adım 2: Yeni ürünler oluşturun \{#step-2-create-new-products\} Test bir fiyat değişikliği içeriyorsa, ikinci adım test varyantı için yeni ürünler oluşturmanıza yardımcı olur. Görsel hipotezler bu adımı atlar. * Sıfırdan yeni bir ürün oluşturmak için **Create a new product and push to stores** düğmesine tıklayın. * Gerekli ürün uygulama mağazası kurulumunuzda zaten mevcutsa **Connect an existing product** düğmesine tıklayın. ## Adım 3: Segment ve paywall'u ayarlayın \{#step-3-set-up-segment-and-paywall\} Üçüncü adım, paywallın test varyantını ayarlamanızı sağlar. Adapty, paywall'ı çoğaltmanızı ve önerilen değişiklikleri uygulamanızı ister. **Coğrafi fiyatlandırma hipotezleri** için sihirbaz, mevcut bir coğrafi sınırlı segment seçmenizi veya yeni bir segment oluşturmanızı ister. Yeni paywall hazır ve segment ayarlandığında **Next** düğmesine tıklayın. ## 4. Adım: İncele ve başlat \{#step-4-review--launch\} Son adım, yapılacak testin özetidir. Şunları içerir: - Her iki **Varyant A ve Varyant B** için temel metrikler — paywall adı, ürün seçimi, deneme süresi ve fiyat. - Test için **Duration**, **Traffic** (bölünme) ve **Subscribers** (minimum örnek boyutu). - Testin başarısını hangi sinyallerin gösterdiğini açıklayan bir **How to interpret results** bölümü. Yapılandırmayı inceleyin ve A/B testini başlatmak için **Launch Test** butonuna tıklayın. --- # File: how-adapty-analytics-works --- --- title: "Adapty analitiği nasıl çalışır" description: "Abonelik performansını verimli bir şekilde takip etmek için Adapty analitiğinin nasıl çalıştığını öğrenin." --- Bu makale, Adapty Analitiği'nin nasıl çalıştığını açıklar: hangi verileri gösterdiğini, verilerin nereden geldiğini ve nasıl işlendiğini. Ayrıca Adapty Analitiği'ni farklı kılan tasarım kararlarını ve bu kararların size ne gibi faydalar sağladığını da ele alır. ## Adapty Analitiği ve mağaza analitiği \{#adapty-analytics-vs-store-analytics\} - **Veri çeşitliliği**: Mağazalar yalnızca kendi verilerini gösterebilir; uygulama içindeki kullanıcı davranışlarına erişemez. Adapty, birden fazla mağazadan gelen verileri pazarlama platformları ve reklam ağları gibi ek kaynaklarla birleştirebilir. Adapty SDK, kullanıcıların paywall ve onboarding etkileşimlerini takip eder. - **Güncelleme sıklığı**: Uygulama mağazaları genellikle verilerini günde bir kez günceller; bu durum gerçek zamanlı karar almanızı kısıtlayabilir. Adapty, [gerçek zamana yakın](#data-processing) analitik sunar. - **Gelişmiş metrikler**: Uygulama mağazaları indirme sayısı, gelir ve elde tutma oranı gibi temel metrikler gösterir. Adapty ise yinelenen gelir veya kullanıcı başına ortalama gelir gibi gelişmiş metrikleri de hesaplar. Abonelik sorunlarını analiz etmeye yönelik özel bölümler mevcuttur: kullanıcı kaybı, ödeme hataları vb. Tam liste için [Metrik karşılaştırma tablosu](metric-comparison-table) makalesine bakabilirsiniz. - **Tahminler**: Adapty, [gelecekteki LTV ve geliri tahmin etmek](predicted-ltv-and-revenue) için gelişmiş makine öğrenmesi algoritmaları kullanır. ## Veri ve Kaynakları \{#data-and-its-sources\} Adapty Analytics, aşağıdaki verileri işleyerek [grafik ve şemalar](analytics) oluşturur: - Kullanıcı yaşam döngüsü boyunca oluşturulan [abonelik olayları](events) — deneme başlangıçları, satın almalar, yenilemeler, iptaller, faturalandırma hataları, iadeler. Adapty bunları [analitik grafikler](analytics)e toplar ve gerçek zamanlı olarak [webhook'lar](webhook)a, [olay akışı](event-feed)na ve [olay tabanlı entegrasyonlar](analytics-integration)a iletir. - [İşlem verileri](revenue) — gelir, iadeler, alıcının ülkesi vb. - Kurulum sayısı veya [paywall etkileşimleri](paywalls) gibi **uygulama verileri**. - [İşlemler için attribution verisi](attribution-integration): trafik kaynakları ve reklam kampanyaları. Bu veriler aşağıdaki kaynaklardan gelir: - <InlineTooltip tooltip="Adapty SDK">[iOS](ios-sdk-overview), [Android](android-sdk-overview), [React Native](react-native-sdk-overview), [Flutter](flutter-sdk-overview), [Unity](unity-sdk-overview), [Kotlin Multiplatform](kmp-sdk-overview), [Capacitor](capacitor-sdk-overview) </InlineTooltip>, uygulama içinden kullanıcı davranışı verilerini raporlar. Adapty satın alma akışı yönetiminizi üstleniyorsa, SDK satın alma etkinlikleri hakkında birincil bilgileri paylaşır. [Gözlemci modu](observer-vs-full-mode) kullanıyorsanız SDK, manuel olarak kurduğunuz [etkinlik raporlarını](report-transactions-observer-mode) alır. - Mağazalar, işlemleri (denemeler, abonelik yenilemeleri, iptaller vb.) Adapty'ye bildirmek için sunucudan sunucuya iletişim kullanır. - Üçüncü taraf [attribution servisleri](attribution-integration) (Appsflyer, Adjust, Branch vb.), trafik kaynakları ve reklam kampanyaları hakkında veri paylaşır. [Adapty Attribution](adapty-user-acquisition) kurarsanız, Adapty reklam kampanyası verilerinizi bu adımı atlayarak kendi başına yönetebilir. - Kullanıcılar, Adapty'nin analiz edip görüntülemesi için [geçmiş işlem verilerini manuel olarak içe aktarabilir](importing-historical-data-to-adapty). Kaynaklardan birinde yaşanan bir sorun, analitik verilerinizin genel kalitesini olumsuz etkileyebilir. Daha fazla bilgi için [Sorun giderme](#troubleshooting) bölümünü inceleyin. ## Üçüncü taraf entegrasyonları \{#third-party-integrations\} Adapty'nin analitik yeteneklerini reklam kampanyası verileriyle genişletmek için [Adapty Attribution](adapty-user-acquisition)'ı etkinleştirebilirsiniz. Bu sayede reklam harcamaları ile kullanıcı davranışları arasındaki ilişkileri keşfedebilirsiniz. Benzer şekilde, analitik verileri üçüncü taraf platformlara veya [özel bir sunucuya](webhook) [dışa aktarabilir](analytics-integration) ve Adapty'den gelen verileri farklı bir platformda analiz edebilirsiniz. ## Veri işleme \{#data-processing\} Adapty, kullanıcıların temel metriklerdeki değişikliklere hızlıca tepki verebilmesi için gerçek zamana yakın analitik sunar. - **Analytics grafikleri**: veriler, bir işlem gerçekleştikten sonra **15–30 dakikalık gecikmeyle** görünür. Adapty'nin işlemi doğrulaması, komisyon ve vergileri uygulaması ve verileri toplaması için bu süreye ihtiyacı vardır. - **[Olay akışı](event-feed)**: mağazalar bir olay iletir iletmez gerçek zamanlı olarak güncellenir. - **[Webhook'lar](webhook) ve olay tabanlı entegrasyonlar** (AppsFlyer, Branch vb.): Adapty olayları gerçekleştiği anda iletir — 15–30 dakikalık analytics gecikmesi burada geçerli değildir. Alıcı servis kendi işleme süresini ekleyebilir. Her yüzeyin kendine özgü bir zamanlaması vardır. Aynı olay; grafiklerde, Event Feed'de ve entegrasyonlarınızda birbirinden biraz farklı zamanlarda görünebilir. Aralarındaki küçük farklılıklar normaldir. ## Komisyonlar ve vergiler \{#commissions-and-taxes\} Gelirle ilgili grafikleri görüntülerken **Gross revenue**, **Revenue after commissions** ve **Revenue after commissions and taxes** seçenekleri arasından tercih yapabilirsiniz. ### Komisyonlar \{#commissions\} Mağazalar her işlemden komisyon keser. Kuruluşunuz indirimli komisyon programına kayıtlıysa, komisyon oranı hesaplamalarını değiştirmek için Adapty ayarlarınızı güncelleyin: * [App Store Small Business Program](app-store-small-business-program) * Google'ın [indirimli hizmet ücreti programı](google-reduced-service-fee) Mağazalar, işlem komisyonunuzu düşüren diğer faktörleri otomatik olarak bildirir: * [1 yıl ve üzeri App Store abonelikleri için yenilemeler](https://developer.apple.com/app-store/subscriptions/) — %15 komisyon * Ülkeye özel oranlar (örneğin, [Japonya'da dağıtılan App Store uygulamaları için %21](https://developer.apple.com/support/app-distribution-in-japan/#business-terms)) ### Vergiler \{#taxes\} **Adapty vergi hesaplamaz.** Vergi oranını Apple ve Google belirler; her işlem için bu değeri Adapty'ye bildirirler ve Adapty de değeri olduğu gibi görüntüler. Belirli bir işlem için gösterilen vergi oranı şunlara bağlıdır: - **Alıcının fatura ülkesi** ve orada geçerli yerel vergi oranı. - **Mağazanın vergi işleme kuralları**. Bazı ülkelerde mağaza, geliştiricinin adına vergiyi tahsil edip öder; bazılarında bu sorumluluk geliştiriciye aittir. - App Store işlemlerinde, uygulamaya veya uygulama içi satın alma işlemine atanan **vergi kategorisi** (kitaplar, haberler, videolar vb.) — kategoriler, yerel kurallara göre farklı oranlarda vergilendirilebilir. Vergi oranları uygulamalar arasında önemli ölçüde farklılık gösterebilir — hatta aynı uygulama içindeki işlemler arasında bile — çünkü alıcı ülkelerin karması, mağazaların uygulama kuralları ve (App Store için) atanan vergi kategorisi bu oranları etkiler. Yetkili kurallar için mağazaların resmi belgelerine bakın: - [App Store: Vergileri anlama](https://developer.apple.com/help/app-store-connect/making-payments-to-apple/understanding-taxes/) - [Google Play: Vergi oranları ve KDV](https://support.google.com/googleplay/android-developer/answer/138000) ## Sorun Giderme \{#troubleshooting\} :::link Ana makale: [Tutarsızlıklar ve Sorun Giderme](discrepancies-and-troubleshooting) ::: * Yanlış yapılandırılmış veya eksik bir veri kaynağı, tüm analitik sistemi olumsuz etkileyebilir. Veri sorunlarıyla karşılaşırsanız, mağazalar ve üçüncü taraf platformlarla entegrasyonlarınızın yapılandırıldığından ve etkin olduğundan emin olun. * Adapty grafiklerini diğer analitik platformlarıyla karşılaştırdığınızda tutarsızlıklar fark edebilirsiniz. Bu beklenen bir davranıştır ve veri işlemedeki farklılıklardan kaynaklanabilir. Yaygın veri tutarsızlığı nedenlerini öğrenmek için [tutarsızlıklar rehberi](discrepancies-and-troubleshooting) makalesini okuyun. --- # File: metric-comparison-table --- --- title: "Farklı metrikleri karşılaştırın" description: "Kategori bazında düzenlenmiş Adapty analytics metriklerine ait referans tabloları." --- Bu sayfa, Adapty Analytics'te mevcut metriklere genel bir bakış sunar. Her metriğin neyi ölçtüğünü ve benzer metriklerden nasıl ayrıldığını anlamak için kullanabilirsiniz. Adapty'nin analitik verilerini nasıl işlediğine dair daha ayrıntılı bir açıklama için bkz. [Adapty analytics nasıl çalışır](how-adapty-analytics-works). :::note Bu makale [Adapty Attribution](adapty-user-acquisition) metriklerini kapsamaz. Reklam kampanyası metrikleri (Harcama, CPI, ROAS, CTR ve diğerleri) hakkında daha fazla bilgi edinmek için [Adapty Attribution analitiği](ua-analytics) bölümünü okuyun. ::: ## Global metrikler \{#global-metrics\} Global metrikler, tüm placement'lar ve paywall'lar genelinde uygulamanızın genel performansını izler. ### Gelir \{#revenue\} Bu metrikler, uygulamanın ne kadar para kazandırdığını ve bu gelirin hangi kaynaklardan geldiğini ölçer. | Metrik | Açıklama | Temel fark | |--------|----------|------------| | [Gelir](revenue) | Aboneliklerden ve tek seferlik satın almalardan elde edilen toplam gelir, iadeler düşülmüş | Fiilen elde edilen gelir. [Grafik kontrollerine](controls-filters-grouping-compare-proceeds) bağlı olarak brüt gelir, komisyon sonrası gelir veya vergi ve komisyon sonrası gelir olarak gösterilebilir | | [MRR](mrr) | Aktif aboneliklerden elde edilen aylık yinelenen gelir | Uygulamanızın öngörülebilir aylık geliri. Tek seferlik satın almaları ve yinelenmeyen abonelikleri kapsamaz. | | [ARR](arr) | Aktif aboneliklerden elde edilen yıllık yinelenen gelir | MRR gibi hesaplanır, ancak yıllık ölçekte. Yıllık geliri tahmin etmek için kullanışlıdır | | [ARPU](arpu) | Kullanıcı başına ortalama gelir | Geliri, ödeme yapan ve yapmayan tüm kullanıcı sayısına böler. Her kullanıcının ortalama ne kadar gelir ürettiğini gösterir | | [ARPPU](arppu) | Ödeme yapan kullanıcı başına ortalama gelir | Yalnızca seçilen dönemde satın alma yapan kullanıcıları (iade edilen işlemler dahil) hesaba katar. Her zaman ARPU'dan yüksektir | | [LTV (yaşam boyu değer)](ltv) | Ödeme yapan müşterilerden elde edilen gelirin bir kohortdaki ödeme yapan müşteri sayısına bölümü | Ödeme yapan müşteri başına zaman içinde gerçekleşen değer. Tek dönemi kapsayan ARPPU'nun aksine, LTV müşteri ilişkisi boyunca toplam geliri gösterir. Yenilemeler veya takvim günleri bazında görüntülenebilir | | [Tahmin edilen LTV](predicted-ltv-and-revenue) | Bir kohortdaki kullanıcı başına tahmini yaşam boyu değer | İleriye dönük tahmin. Gerçekleşen LTV'nin aksine, geçmiş kohort elde tutma kalıplarından gelecekteki değeri öngörür. 3, 6, 9, 12, 18 ve 24 ay için kullanılabilir | | [Tahmin edilen gelir](predicted-ltv-and-revenue) | Bir kohortun üreteceği tahmini toplam gelir | İleriye dönük tahmin. Gerçekleşen Gelir'in aksine, bir kohortun seçilen zaman diliminde üreteceği toplam tutarı öngörür. Her gün güncellenir | | [Abonelik dışı satın almalar](non-subscriptions) | Uygulama içi satın alma sayısı: consumable'lar, non-consumable'lar ve yinelenmeyen abonelikler | Otomatik yenelenen abonelikleri kapsamaz. | | [İade olayları](refund-events) | İade edilen satın alma veya abonelik sayısı | Orijinal satın alma tarihine değil, iade tarihine göre atfedilir. | | [İade tutarı](refund-money) | Seçilen dönemde iade edilen toplam tutar | İadelerin finansal etkisi. Mağaza ücretleri alınmadan hesaplanır. Bir sayı olan İade olayları'nın aksine, bu metrik parasal tutarı gösterir | ### Aboneler ve dönüşüm \{#subscribers-and-conversion\} Bu metrikler, kullanıcıların uygulamaya nasıl girdiğini ve huniden nasıl ilerlediğini izler. | Metrik | Açıklama | Temel fark | |--------|----------|------------| | [Yüklemeler](installs) | Dönem içindeki uygulama yükleme sayısı | [Yükleme tanımına](general#4-installs-definition-for-analytics) bağlı olarak aşağıdakilerden birini sayar: <br /> • Cihaz yüklemeleri (uygulamayı yeniden yükleyen kullanıcı tekrar sayılır) <br /> • Benzersiz kullanıcılar (yalnızca `customer_user_id` ayarlayan kullanıcıları sayar. Anonim kullanıcılar tamamen dışarıda bırakılır — hiçbir kullanıcı tanımlanmamışsa sayı 0 olur) | | [Yeni denemeler](new-trials) | Dönem içinde başlatılan denemeler | Grafiği görüntülediğinizde deneme süresi dolmuş veya ücretli aboneliğe dönüşmüş olsa bile her deneme başlangıcını sayar | | [Aktif denemeler](active-trials) | Henüz süresi dolmamış deneme sayısı | Yalnızca dönem sonunda aktif olan denemeleri sayar | | [Yeni abonelikler](reactivated-subscriptions) | Dönem içinde ilk kez etkinleştirilen abonelikler; deneme olmadan yapılan ilk satın almalar ve denemeden ücretliye geçişler dahil | Yenilemeler ve yeniden aktivasyonlar hariçtir. Yalnızca deneme olmadan yapılan ilk satın almaları sayan `subscription_started` entegrasyon etkinliğiyle aynı şey değildir — deneme dönüşümleri bunun yerine `trial_converted` tetikler | | [Aktif abonelikler](active-subscriptions) | Henüz süresi dolmamış ücretli abonelik sayısı | Denemeler ve yenileme iptali olan abonelikler hariçtir | | [Yüklemeden denemeye](analytics-conversion#install---trial) | Deneme başlatan yükleyicilerin yüzdesi | Payda, yalnızca paywall görüntüleyenleri değil tüm yükleyicileri kapsar; bu nedenle oran Paywall görüntülemeden denemeye oranından düşük olabilir. Uygulama paywall görüntülemelerini kaydetmiyorsa iki metrik de birbirinden sapabilir. Bu durum, `logShowFlow` (iOS SDK v4+) / `logShowPaywall` çağırmayan özel bir paywall kullanıldığında veya kullanıcı denemesini [tanıtılan uygulama içi satın alma](https://developer.apple.com/documentation/storekit/supporting-promoted-in-app-purchases-in-your-app) üzerinden başlattığında yaşanabilir. | | [Paywall görüntülemeden denemeye](analytics-conversion#paywall-view---trial) | Deneme başlatan paywall görüntüleyicilerin yüzdesi | Yalnızca paywall gören kullanıcıları sayar; bu nedenle oran Yüklemeden denemeye oranından yüksek olabilir | | [Denemeden ücretliye](analytics-conversion#trial---paid) | Abonelik satın alan deneme kullanıcılarının yüzdesi | Deneme kalitesini ve dönüşüm verimliliğini ölçer. Yüklemeden ücretliye metriğinin aksine, yalnızca denemeyi tamamlayan kullanıcılara odaklanır | | [Yüklemeden ücretliye](analytics-conversion#install---paid) | İlk aboneliği satın alan yükleyicilerin yüzdesi | Yalnızca paywall görüntüleyenleri değil tüm yükleyicileri sayar. Oran, Paywall görüntülemeden ücretliye oranından düşük olabilir. Hem doğrudan satın almaları hem de denemeden ücretliye dönüşümleri içerir | | [Paywall görüntülemeden ücretliye](analytics-conversion#paywall-view---paid) | Sonunda abonelik satın alan paywall görüntüleyicilerin yüzdesi | Yalnızca paywall gören kullanıcıları sayar; bu nedenle oran Yüklemeden ücretliye oranından yüksek olabilir. Önce denemeyi tamamlayan kullanıcıları da kapsar | ### Kullanıcı tutma ve abonelik yenileme \{#retention-and-subscription-renewal\} Bu metrikler, uygulamanın ödeme yapan aboneleri zaman içinde ne kadar iyi tuttuğunu gösterir. | Metrik | Açıklama | Temel fark | |--------|----------|------------| | [Retention](analytics-retention) | Her faturalandırma döneminden sonra kalan orijinal abonelerin oranı — 1. yenileme, 2. yenileme vb. | Aboneleri ilk ödemeden itibaren takip eder. Aşağıdaki dönemden döneme metriklerin aksine, her zaman orijinal grupla karşılaştırır; bu sayede genel tabloya tek bakışta ulaşırsınız | | [Ödeyenden 2. döneme](analytics-conversion#paid---2nd-period) | İlk kez abone olanların ikinci dönem için yenileme yüzdesi | İki belirli ardışık dönem arasındaki geçişi ölçer. Retention'ın aksine, en kritik tek yenilemeye — yani ilk yenilemeye — odaklanır | | [2. dönemden 3. döneme](analytics-conversion#2nd-period---3rd-period) | 2. dönemden 3. döneme yenileme yüzdesi | İlk yenilemenin ardından erken dönem retention kararlılığını gösterir | | [3. dönemden 4. döneme](analytics-conversion#3rd-period---4th-period) | 3. dönemden 4. döneme yenileme yüzdesi | Orta vadeli retention göstergesi | | [4. dönemden 5. döneme](analytics-conversion#4th-period---5th-period) | 4. dönemden 5. döneme yenileme yüzdesi | Uzun vadeli sadakat göstergesi | | [6 Ay+](analytics-conversion#6-months-) | İlk kez abone olanların 6 ayı aşkın süre aboneliğini sürdürme yüzdesi | Yenileme sayısını değil, takvim süresini ölçer. Yıllık bir abone, yenileme yapmadan da 6 aylık sürede aktif sayılır | | [1 Yıl+](analytics-conversion#1-year-) | İlk kez abone olanların 12 ayı aşkın süre aboneliğini sürdürme yüzdesi | Yıllık retention kilometre taşı | | [2 Yıl+](analytics-conversion#2-years-) | İlk kez abone olanların 24 ayı aşkın süre aboneliğini sürdürme yüzdesi | Uzun vadeli retention kilometre taşı | ### Churn \{#churn\} Bu metrikler, uygulamanın kaç abone ve deneme kullanıcısı kaybettiğini ölçer. | Metrik | Açıklama | Temel fark | |--------|----------|------------| | [Yenileme iptal edilen denemeler](trials-renewal-cancelled) | Kullanıcının otomatik yenilemeyi devre dışı bıraktığı denemeler | Kullanıcı deneme süresi dolana kadar erişimini korur ancak ücretli aboneliğe otomatik olarak geçmez. Subscriptions renewal cancelled'dan farklı olarak, henüz ödeme yapmamış deneme kullanıcıları için geçerlidir | | [Süresi dolan (kaybedilen) denemeler](expired-churned-trials) | Süresi dolan denemeler — kullanıcı premium özelliklere erişimini kaybetti | Kullanıcı erişimini zaten kaybetmiştir. Kullanıcı yenilemeyi önceki bir dönemde iptal etmiş olsa bile sona erme tarihine atfedilir. Nedene göre gruplandırılabilir (gönüllü veya faturalama kaynaklı) | | [Yenileme iptal edilen abonelikler](cancelled-subscriptions) | Kullanıcının otomatik yenilemeyi devre dışı bıraktığı abonelikler | Kullanıcı dönem sonuna kadar erişimini korur. Gerçek bir kayıp değil, kayıp riskine işaret eder — kullanıcı dönem sona ermeden önce otomatik yenilemeyi yeniden etkinleştirebilir | | [Kaybedilen (süresi dolan) abonelikler](churned-expired-subscriptions) | Süresi dolan abonelikler — kullanıcı premium özelliklere erişimini kaybetti | Gerçek kayıp. Kullanıcı erişimini zaten kaybetmiştir. Kullanıcı yenilemeyi önceki bir dönemde iptal etmiş olsa bile sona erme tarihine atfedilir. Nedene göre gruplandırılabilir (gönüllü veya faturalama kaynaklı) | ### Faturalandırma sorunları ve gelir kurtarma \{#billing-issues-and-revenue-recovery\} Bu metrikler, uygulamanın faturalandırma sorunlarından kaynaklanan geliri ne kadar etkin biçimde kurtardığını takip eder. | Metrik | Açıklama | Temel fark | |--------|----------|------------| | [Ek süre](grace-period) | Ödeme hatası nedeniyle ek süreye giren abonelikler | Ek süreyi aşıp erişimini kaybeden kullanıcıları da içerir | | [Ek süreden ödemeye geçiş](analytics-conversion#grace-period---paid) | Ek süre sona ermeden yenileyen ek süre kullanıcılarının yüzdesi | Bir oran (%). "Ek süredeki kullanıcıların ne kadarı kurtarıldı?" sorusunu yanıtlar | | [Ek süre dönüşümü](grace-period-converted) | Başarıyla yenilenen ek süre aboneliklerinin mutlak sayısı | Ek süreden ödemeye geçiş ile aynı olaylar, ancak yüzde yerine sayı olarak gösterilir | | [Ek süre dönüşüm geliri](grace-period-converted-revenue) | Ek süre kurtarmalarından elde edilen gelir | Ek süre özelliğinin finansal etkisi | | [Ödeme sorunu](billing-issue) | Ödeme sorunu durumuna giren abonelikler | Ek süre sona erdikten sonra başlar. Ek sürenin aksine, yalnızca premium erişimini zaten kaybetmiş kullanıcıları sayar | | [Ödeme sorununda ödemeye geçiş](analytics-conversion#billing-issue---paid) | Faturalama döngüsü sona ermeden yenileyen ödeme sorunlu kullanıcıların yüzdesi | Bir oran (%). "Ödeme sorunu yaşayan kullanıcıların ne kadarı kurtarıldı?" sorusunu yanıtlar | | [Ödeme sorunu dönüşümü](billing-issue-converted) | Başarıyla yenilenen ödeme sorunlu aboneliklerin mutlak sayısı | Başarıyla yenilenen ödeme sorunlu aboneliklerin sayısı. Ödeme sorununda ödemeye geçiş ile aynı olaylar, ancak yüzde yerine sayı olarak gösterilir | | [Ödeme sorunu dönüşüm geliri](billing-issue-converted-revenue) | Ödeme sorunu kurtarmalarından elde edilen gelir | Ödeme sorunu kurtarmanın finansal etkisi | ## Paywall, placement ve onboarding metrikleri \{#paywall-placement-and-onboarding-metrics\} Bu metrikler, her bir [paywall](paywall-metrics), [placement](placement-metrics) ve onboarding için ayrı ayrı hesaplanır. Belirli bir paywall veya placement'ın performansını ölçer; uygulamanın genelini değil. **Associated global metric** sütunu, global analitik bölümündeki ilgili metriği gösterir. | Metrik | Açıklama | Temel fark | İlgili global metrik | |--------|----------|------------|-------------| | [Proceeds](paywall-metrics#proceeds) | Bir placement için vergi ve komisyon sonrası gelir | Vergi ve komisyon sonrası [Revenue](revenue) ile eşdeğer | [Revenue](revenue) | | [ARPPU](paywall-metrics#arppu) | Bu paywall veya placement için ödeme yapan kullanıcı başına ortalama gelir | Global ARPPU ile aynı hesaplama ancak tek bir paywall veya placement kapsamında | [ARPPU](arppu) | | [ARPAS](paywall-metrics#arpas) | Aktif abone sayısına (deneme ve ücretli) bölünen gelir | Deneme kullanıcılarını sayar. ARPPU'dan farklı olarak tüm abone tabanının gelir potansiyelini yansıtır | — | | [Views](paywall-metrics#views) | Bir paywall veya placement'ın gösterildiği toplam sayı | Her gösterimi sayar. Aynı paywall'ı iki kez görüntüleyen tek bir kullanıcı 2 görüntüleme olarak sayılır | — | | [Unique views](paywall-metrics#unique-views) | Bir paywall veya placement'ı gören benzersiz kullanıcı sayısı | Her kullanıcı, kaç kez görüntülediğinden bağımsız olarak bir kez sayılır. Views'ın aksine, etkileşim sıklığı yerine erişimi ölçer | — | | [CR to purchases](paywall-metrics#cr-to-purchases) | Satın almalar toplam görüntülemeye bölünür | Payda olarak toplam görüntülemeyi (aynı kullanıcının tekrar görüntülemeleri dahil) kullanır | [Paywall view to paid](analytics-conversion#paywall-view---paid) | | [Unique CR to purchases](paywall-metrics#unique-conversion-rate-cr-to-purchases) | Satın almalar benzersiz görüntülemeye bölünür | Payda olarak benzersiz görüntülemeyi kullanır. Tekrar görüntüleyenler bir kez sayıldığından benzersiz olmayan CR'dan daha yüksek orandır | [Paywall view to paid](analytics-conversion#paywall-view---paid) | | [CR to trials](paywall-metrics#unique-cr-to-trials) | Başlatılan denemeler toplam görüntülemeye bölünür | Bir paywall'ın görüntülemeleri ne kadar etkili şekilde denemeye dönüştürdüğünü ölçer | [Paywall view to trial](analytics-conversion#paywall-view---trial) | | [Unique CR to trials](paywall-metrics#unique-cr-to-trials) | Başlatılan denemeler benzersiz görüntülemeye bölünür | CR to trials gibi hesaplanır ancak payda olarak benzersiz görüntüleyenler kullanılır | [Paywall view to trial](analytics-conversion#paywall-view---trial) | | [Purchases](paywall-metrics#purchases) | Bu paywall için toplam işlem sayısı: yeni satın almalar, deneme dönüşümleri, yükseltmeler, düşürmeler ve geri dönen abonelikler | Yenilemeleri kapsamaz. | [Revenue](revenue) | | [Trials](paywall-metrics#trials) | Bu paywall üzerinden etkinleştirilen toplam denemeler | Yalnızca bu paywall kapsamında | [New trials](new-trials) | | [Trials canceled](paywall-metrics#trials-canceled) | Kullanıcının otomatik yenilemeyi devre dışı bıraktığı deneme sayısı | Yalnızca bu paywall'ın denemeleri kapsamında | [Trials renewal cancelled](trials-renewal-cancelled) | | [Refund rate](paywall-metrics#refund-rate) | İadeler ilk kez yapılan satın almalara bölünür (yenilemeler hariç) | Sayı değil, oran (%). İadeleri satın alma sayısına göre normalleştirir | [Refund events](refund-events) (oran değil, sayı) | | Completions | Kullanıcıların bir onboarding flow'unu ilk ekrandan son ekrana kadar tamamladığı sayı | Yalnızca placement ve onboarding. Aynı kullanıcının tekrar tamamlamaları dahil her tamamlamayı sayar | — | | Unique completions | Bir onboarding flow'unu tamamlayan benzersiz kullanıcı sayısı | Yalnızca placement ve onboarding. Her kullanıcı bir kez sayılır. Completions'ın aksine, flow'u kaç kişinin bitirdiğini ölçer | — | | Unique completions rate | Benzersiz tamamlamalar benzersiz görüntülemeye bölünür | Yalnızca placement ve onboarding. Onboarding etkinliğini ölçer: başlayan kullanıcıların ne kadarı gerçekten bitirdi | — | --- # File: overview --- --- title: "Analitik genel bakış sayfası" description: "Uygulama performansınıza genel bir bakış için birden fazla Adapty analitik grafiğini aynı sayfada görüntüleyin" --- [Genel Bakış sayfası](https://app.adapty.io/overview), tüm uygulamalarınızın birleşik metriklerini tek bir yerde görüntüler. Bu sayfa, kontrol panelinin ana sayfasıdır ve sol menüden de erişilebilir. Tek bir uygulamaya ait verileri görmek için ilgili [grafiği](charts) açın. ## Grafikler \{#charts\} Overview, Adapty'nin [analitik grafiklerinin](charts) özelleştirilebilir bir alt kümesini görüntüler. Mevcut her grafiğin açıklamaları ve yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table) bakın. Hangi grafiklerin ve hangi sırada görüneceğini özelleştirmek için sağ üst köşedeki **Edit** düğmesine tıklayın. Buradan grafikleri kaldırabilir, ekleyebilir veya yeniden sıralayabilirsiniz: Aşağıdaki grafikler kullanılabilir: - [Gelir](revenue) - [MRR](mrr) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) - [ARPAS](placement-metrics#arpas) - [Kurulumlar](installs) - [Yeni denemeler](new-trials) - [Yeni abonelikler](reactivated-subscriptions) - [Aktif denemeler](active-trials) - [Aktif abonelikler](active-subscriptions) - [Yeni abonelik dışı satın almalar](non-subscriptions) - [İade olayları](refund-events) - [İade tutarı](refund-money) - [İptal edilen abonelik yenilemeleri](cancelled-subscriptions) - [Kurulumdan Denemeye, Kurulumdan Ödemeye ve Denemeden Ödemeye dönüşüm oranı](analytics-conversion) ## Kontroller \{#controls\} Genel Bakış sayfası; filtreleme, gruplama ve zaman dilimi karşılaştırması dahil olmak üzere [analiz kontrollerinin](controls-filters-grouping-compare-proceeds) büyük çoğunluğunu destekler. Genel Bakış'a özgü tek özellik, uygulamaya göre gruplama ve filtrelemedir. Sayfa tüm uygulamalarınıza ait verileri bir arada gösterdiğinden, uygulama bazındaki görünüm her uygulamanın iş metriklerine nasıl katkıda bulunduğunu ortaya koyar: ## Yükleme sayısı ve saat dilimi \{#install-count-and-timezone\} Overview, tüm uygulamalarınızdan gelen verileri **kendi saat dilimi ve yükleme sayımı ayarlarıyla** birleştirir; uygulama bazındaki değerler burada geçerli değildir. - **Yüklemeler**: Yüklemelerin nasıl sayılacağını seçin. **By device installations** seçeneği, yeniden yüklemeler dahil her cihaz yüklemesini ayrı olarak sayar. **By unique users** ise yalnızca her tanımlı kullanıcının ilk yüklemesini sayar. Ayarı değiştirmek için **Edit Metrics** seçeneğine tıklayın ve açılır menüden [farklı bir seçenek](general#4-installs-definition-for-analytics) belirleyin. - **Saat Dilimi**: Overview'ın saat dilimini değiştirmek için **Edit Metrics** seçeneğine tıklayın ve açılır menüden bir saat dilimi seçin. Bu özellik, hesabınızdaki farklı uygulamalar farklı saat dilimleri kullanıyorsa özellikle işe yarar. --- # File: controls-filters-grouping-compare-proceeds --- --- title: "Analitik kontrolleri" description: "Adapty analitik verilerinizi filtreleyin, gruplayın ve karşılaştırın." --- Adapty, her analitik sekmesindeki verileri daraltmak için çeşitli kontroller sunar: zaman aralığı, dönem karşılaştırması, filtreleme, gruplama ve grafik görselleştirme. Kullanılabilirlik sekmeye göre farklılık gösterir. **Analitik sekmesine göre kullanılabilir kontroller:** | Kontrol | Grafikler | Kohortlar | Huniler | Elde Tutma | Dönüşüm | LTV | | :--- | :---: | :---: | :---: | :---: | :---: | :---: | | Tarih aralığı | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Dönem karşılaştırması | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | Filtre | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Grup | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | | Grafik görselleştirme | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | Tablo görünümü | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | CSV dışa aktarma | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | Komisyon ve vergiler | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ### Tarih aralığını ayarlama \{#set-the-date-range\} Her grafiğin üzerindeki **Date range** takvimini kullanarak zaman dilimini seçin. Adapty analizleri **UTC saat dilimini** kullanır; [Genel Bakış sayfasının](overview) kendine ait yapılandırılabilir bir saat dilimi vardır. #### Hazır aralıklar \{#preset-ranges\} Özel başlangıç ve bitiş tarihleri belirtmek için **Custom** seçeneğini kullanın. Hazır aralıklar şunlardır: | Ön Ayar | Başlangıç | Bitiş | | --- | --- | --- | | Son 7 gün | 6 gün önce | Bugün | | Son 28 gün | 27 gün önce | Bugün | | Son ay | Önceki aydaki aynı tarih | Bugün | | Son 3 ay | 3 ay önce | Bugün | | Son 6 ay | 6 ay önce | Bugün | | Son yıl | 1 yıl önce | Bugün | | Önceki ay | Önceki ayın ilk günü | Önceki ayın son günü | | Bu ay | Mevcut ayın 1'i | Bugün | | Bu çeyrek | Mevcut çeyreğin 1'i | Bugün | | Bu yıl | Mevcut yılın 1 Ocak'ı | Bugün | :::tip Haftalık abonelik ürünlerini takip etmek için **Last 28 days** seçeneğini kullanın — bu aralık dört tam haftalık döngüyü kapsadığından, kısmi bir hafta karşılaştırmayı etkilemez. ::: #### Zaman ölçeği \{#time-scale\} Grafikteki her veri noktası bir zaman dilimini temsil eder — açılır menüden gün, hafta, ay, çeyrek veya yıl arasında seçim yapabilirsiniz. Gün ve hafta kısa vadeli dalgalanmaları; ay, çeyrek ve yıl ise uzun vadeli eğilimleri gösterir. [kohort](analytics-cohorts) ve [LTV](ltv) analizlerinde aynı ayar **cohort length** olarak adlandırılır — ayrıntılar için ilgili makalelere bakın. ### İki zaman dilimini karşılaştırma \{#compare-two-time-periods\} Mevcut dönemi önceki bir dönemle çakıştırmak için takvimin yanındaki karşılaştırma seçeneğine tıklayın. Adapty'nin varsayılan karşılaştırması, aynı uzunluktaki bir önceki dönemdir. Karşılaştırma aralığını değiştirmek için seçeneğe tekrar tıklayın ve özel bir aralık seçin. Karşılaştırma şu şekilde görünür: - **Grafikte** — sıfır veya bir gruplama seçiliyken üst üste bindirilmiş çizgiler, alanlar veya sütunlar. - **Sayısal değer olarak** — iki dönem arasındaki fark, yeşil (yüksek) veya kırmızı (düşük) renkte gösterilir. - **Araç ipucunda** — herhangi bir veri noktasının üzerine gelerek o noktanın sayısal farkını görebilirsiniz. ### Veriyi Filtrele ve Grupla \{#filter-and-group-data\} Grafiği yalnızca belirli niteliklere uyan verilerle (örneğin tek bir ülke veya ürün) sınırlandırmak için **Filtrele**; grafik toplamını ayrı serilere bölmek için **Grupla** seçeneğini kullanın. Örneğin Geliri ülkeye göre grupladığınızda, tek bir birleşik toplam yerine her ülke için ayrı bir gelir çizgisi elde edersiniz. **Kullanılabilir filtre ve gruplama nitelikleri:** | Özellik | Filtre | Grupla | Açıklama | | --- | :---: | :---: | --- | | Attribution | ✅ | ✅ | Raporlayan, Durum, Kanal, Kampanya, Reklam Grubu, Reklam Seti ve Kreatif (Anahtar Kelime). [Attribution entegrasyonu](attribution-integration) gerektirir. | | Kitle | ✅ | ✅ | Kullanıcının dahil olduğu [kitle](audience). | | Yenileme durumu | ❌ | ✅ | Aboneliğin bir sonraki dönemde yenilenip yenilenmeyeceği. | | Dönem | ✅ | ✅ | Abonelik yaşam döngüsü aşaması: **Trial**, **Aktivasyon** (ilk ödeme) veya **Yenileme 1**–**Yenileme 5**, **Yenileme 6+** (sonraki yenilemeler). | | Ülke | ✅ | ✅ | Kullanıcının mağaza ülkesi. Mevcut değilse Adapty, bunu para birimi kodundan veya cihaz IP'sinden çıkarır. | | Teklif Türü | ✅ | ✅ | İşleme uygulanan teklif: <ul><li>**Introductory** — ilk abonelik dönemindeki başlangıç teklifi. Ücretli başlangıç teklifleri ile ücretsiz denemeler arasında ayrım yapmak için **Teklif İndirim Türü**'nü kullanın.</li><li>**Promotional** — App Store Promosyon Teklifleri ve eşdeğerleri.</li><li>**Offer Code** — müşterinin mağazaya girdiği promosyon kodları.</li><li>**No offer** — herhangi bir teklif uygulanmamış.</li></ul> | | Teklif Kimliği | ✅ | ✅ | Belirli bir teklif kimliği. | | Teklif İndirim Türü | ✅ | ✅ | Başlangıç veya promosyon teklifinin fiyatlandırma modeli: **Free Trial**, **Pay As You Go** veya **Pay Up Front**. Örneğin ücretsiz deneme başlangıcını ücretli başlangıçtan ayırt etmek için **Teklif Türü** ile birleştirin. | | Paywall | ✅ | ✅ | Satın alma için kullanılan [paywall](paywalls). | | A/B testleri | ✅ | ❌ | Satın alma sırasında aktif olan [A/B testi](ab-tests). | | Placement | ✅ | ✅ | Satın almanın gerçekleştiği [placement](placements). | | Mağaza | ✅ | ✅ | İşlemi gerçekleştiren mağaza: App Store, Google Play, Stripe vb. | | Ürün | ✅ | ✅ | [Ürün](product) — abonelikler ve tek seferlik satın almalar. | | Süre | ✅ | ✅ | Ürünün süresi. | | Segment | ✅ | ✅ | Bir kullanıcı [segmenti](segments). Segment performansını **Tüm kullanıcılar** ile karşılaştırmak için segmente göre gruplayın. <ul><li>Dönüşüm hunileri, segmente göre gruplamayı desteklemez.</li><li>Bir segment tarafından kullanıldıktan sonra özel bir özelliği değiştirirseniz, Adapty kullanıcıyı analitikte segmentten dışlayabilir. Veriler önceki değeri göstermeye devam eder.</li></ul> | | İade Nedeni | ✅ | ✅ | Bir işlemin iade edilme nedeni (örneğin, **Refund** veya **Upgraded**). İade ve faturalama sorunu çözüm grafiklerinde kullanılabilir. | | Sona erme nedeni | ❌ | ✅ | Bir aboneliğin veya denemenin sona erme nedeni: **Cancelled by customer**, **Billing issue**, **Customer hasn't agreed to price increase**, **Unknown** veya **Refund**. Süresi Dolmuş (Churn) aboneliklerde ve Süresi Dolmuş (Churn) denemelerde kullanılabilir. | | Kohort (Yalnızca LTV) | ❌ | ✅ | LTV grafiğinde kohort uzunluğuna göre gruplandırın: **Day**, **Week**, **Month** veya **Year**. Bu grafikte Attribution'a Göre Grupla'nın yerini alır. | Her analitik görünümü yukarıdaki tüm filtre veya gruplama özelliklerini desteklemez. Grafikler sekmesindeki ARPU ve Yüklemeler yalnızca Attribution, Ülke, Segment, Mağaza ve (yalnızca filtre olarak) A/B testleriyle sınırlıdır. LTV, Kohortlar, Huniler, Elde Tutma ve Dönüşüm sekmeleri ise her biri farklı bir alt kümeyi destekler. Tam destek bilgisi için ilgili grafik veya sekmenin makalesine bakın. ### Ülke nasıl belirlenir \{#how-country-is-determined\} Her işlem, oluşturulduğu anda bir ülkeyle etiketlenir. Bu ülkenin kaynağı, öncelik sırasına göre şöyledir: 1. İşlem anında kullanıcının **cihaz IP ülkesi**. 2. Kullanıcının **mağaza ülkesi** — App Store veya Google Play hesabının ülkesi. 3. Kullanıcının en son bilinen **IP ülkesi**. Mağaza ülkesi; web ödemeleri (Stripe, Paddle), manuel olarak verilen erişimler veya mağazanın bu bilgiyi sağlamadığı işlemler için mevcut değildir. Bu durumlarda Adapty, IP tabanlı ülkeye geri döner. Ülke, işlem başına kaydedildiğinden, kurulumdan sonra App Store ülkesini değiştiren bir kullanıcının önceki ve sonraki işlemlerinde farklı ülke değerleri görünür. Geçmiş işlemler özgün ülkelerini korur. **GB ve United Kingdom.** Ülke verisi ISO 3166-1 alfa-2 kodları olarak saklanır (yani "United Kingdom" değil, "GB"). Kontrol panelinin görüntüleme katmanı, kodları tam adlara çevirmek için bir arama tablosu kullanır; bu tabloda eski bir `'UK' → 'United Kingdom'` takma adı bulunur — segment oluştururken her ikisinin de seçenek olarak çıkmasının nedeni budur. ### Grafik görselleştirmesini değiştirin \{#change-the-chart-visualization\} Grafiğin nasıl görüntüleneceğini görselleştirme açılır menüsünden seçin: - **Yığılmış sütun** — her sütun, grup başına renkli segmentlere bölünmüş toplam değeri gösterir. - **Yığılmış alan** — yığılmış sütunla aynıdır; ancak veri noktalarını birleştiren dolu alanlar kullanılır. - **Çizgi** — her grup için ayrı bir çizgi; dolgu yok. - **%100 yığılmış sütun** — her sütun grafiğin tam yüksekliğine ulaşır; segmentler gerçek değerler yerine her grubun göreli payını (yüzde olarak) gösterir. Zaman içindeki oranları incelemek için kullanışlıdır. - **%100 yığılmış alan** — %100 yığılmış sütunla aynıdır; ancak sütunlar yerine dolu alanlar kullanılır. ### Tablo görünümü \{#table-view\} Grafik görünümüne ek olarak, Adapty her grafik için tablo görünümü de sunar. Tablo görünümü, grafiği oluşturmak için kullanılan verileri tablolu bir formatta göstererek kullanıcıların verileri daha ayrıntılı inceleyip analiz etmesine olanak tanır. Tablo görünümü, verilerle daha yapılandırılmış bir şekilde çalışmayı tercih edenler ya da Adapty dışında daha ileri analiz yapmak için verileri dışa aktarması gerekenler için kullanışlı bir araçtır. ### CSV veri dışa aktarımı \{#csv-data-export\} Grafikler, kohort analizleri, huniler, elde tutma veya dönüşüm analizlerinin arkasındaki ham verileri incelemek için **Export** düğmesine tıklayarak CSV formatında dışa aktarabilirsiniz. <img src="/assets/shared/img/03eee2c-CleanShot_2023-07-10_at_20.49.152x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Aynı verileri [API aracılığıyla da alabilirsiniz](export-analytics-api). Hangi yöntemi kullanırsanız kullanın, veri dosyası aynı olacaktır. Bu özellik, ham verilere erişmenizi sağlar; bu verileri daha derin içgörüler elde etmek için elektronik tablo uygulamalarında veya başka araçlarda daha ayrıntılı inceleyebilirsiniz. ### Brüt veya net geliri görüntüleme \{#display-gross-or-net-revenue\} Gelirle ilgili grafikler için ([Gelir](revenue), [MRR](mrr), [ARR](arr), [ARPU](arpu), [ARPPU](arppu)), Adapty üç görüntüleme modu sunan bir açılır menü sunar: - **Gross revenue** — herhangi bir kesinti yapılmadan önceki toplam gelir. - **Proceeds after store commission** — mağaza komisyonu düşüldükten sonraki gelir; vergiler hâlâ dahildir. - **Proceeds after store commission and taxes** — hem komisyon hem de vergiler düşüldükten sonraki gelir. Komisyon ve vergi hesaplamaları hakkında ayrıntılı bilgi için *Adapty Analytics nasıl çalışır* bölümündeki [Komisyonlar ve vergiler](how-adapty-analytics-works#commissions-and-taxes) konusuna bakın. --- # File: revenue --- --- title: "Gelir" description: "Adapty'nin abonelik analizleriyle uygulamanızın gelirini takip edin ve analiz edin." --- Gelir grafiği, hem aboneliklerden hem de tek seferlik satın almalardan elde edilen toplam geliri, daha sonra iade edilen gelir düşüldükten sonra gösterir. Uygulamanızın finansal performansını takip etmek için kullanabileceğiniz birincil metriktir. Son 12 ayın genel trendlerini değerlendirmek için aylık çözünürlüğe geçin. Gelirin nereden geldiğini görmek için grafiği ürüne, kullanıcı segmentine veya attribution kaynağına göre gruplayın; büyümeyi hangi tarafın sürüklediğini anlamak için yeni-yenileme karışımını takip edin. ## Hesaplama \{#calculation\} :::warning Aşağıdaki hesap makinesi [mağaza komisyonu ve vergilendirmeyi](how-adapty-analytics-works#commissions-and-taxes) **dikkate almaz**. Sonucu **brüt gelir** hesaplamalarınızla karşılaştırın. ::: Gelir, dönem içindeki tüm ücretli işlemlerin toplamından (yeni abonelikler, yenilemeler, deneme sürümü dönüşümleri, tek seferlik satın almalar) dönem içinde işlenen iadeler çıkarıldıktan sonra kalan tutardır: **Gelir = toplam işlemler − iadeler**. Her işlemin tam tutarı, aboneliğin süresi boyunca dağıtılmak yerine satın alma gününe kaydedilir. Grafik varsayılan olarak brüt geliri gösterir. Brüt, komisyon sonrası veya komisyon ve vergi sonrası görünümler arasında geçiş yapmak için [grafik kontrollerini](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) kullanın. <CompoundCalculator client:load heading="Gelir" formuLatex="\sum P_i \times Q_i - D" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "Birim fiyat", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "Miktar", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "İade edilen tutar", variableValue: 35, global: true } ]} rowFormula="price * qty" resultFormula="_sum - refunds" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## İade işleme \{#refund-handling\} Gelir, her iadeyi orijinal satın alma tarihine değil, iadenin işlendiği tarihe göre düşer. Belirli bir grup veya gün için iadeler yeni geliri aştığında grafik negatif bir değer gösterebilir. Metrikler genelinde tam karşılaştırma için bkz. [Metrikler iadeleri nasıl işler](refund-events#how-metrics-handle-refunds). ## Para Birimi \{#currency\} Adapty tüm parasal grafikleri, orijinal işlem para biriminden bağımsız olarak **ABD doları** cinsinden görüntüler. Bu durum; Gelir, MRR, ARR, ARPU, ARPPU, LTV, tahmin edilen gelir, iade tutarları ve kohort ile A/B testi raporlarındaki gelir rakamlarını kapsar. Başka bir para biriminde görüntüleme ayarı mevcut değildir. Adapty, her işlemi [currencylayer.com](https://currencylayer.com/) üzerinden her 8 saatte bir yenilenen ve **işlem anında sabitlenen** bir kur üzerinden ABD dolarına çevirir. Geçmiş USD değerleri, kur değişimlerinde yeniden hesaplanmaz. Yerel para birimi değerlerine işlem bazında şu yerlerden ulaşabilirsiniz: - Webhook'lardaki `price_local` ve `currency` alanları - S3, GCS ve BigQuery dışa aktarımlarındaki `_local` sütunları (örneğin `revenue_local` ve `proceeds_local`) ve `currency` - Profil sayfası (işlem bazında görünüm) Yerel para biriminde finans raporlaması yapmak için, dışa aktarımdan işlem bazındaki yerel para birimi değerlerini alıp kendiniz toplamanız gerekir. ## Yenileme fiyatlandırması \{#renewal-pricing\} Adapty, yenileme gelirini ürünün mevcut fiyatı üzerinden hesaplar; bu, aboneliğe ilk kaydolduklarında önceki bir fiyattan yararlanan kullanıcılar için de geçerlidir. App Store Connect veya Google Play'de fiyatı değiştirmenizin ardından, mevcut aboneler için kontrol panelindeki Revenue, MRR ve ARR rakamları gerçekte tahsil edilen gelirden sapabilir — Adapty, mağazanın bu kullanıcıları eski fiyatta tutmuş olmasına rağmen yeni fiyatı uygular. Doğrulamak için, aynı işlemler üzerinde S3, GCS veya BigQuery dışa aktarımındaki işlem başına `price` alanını kontrol paneliyle karşılaştırın. Dışa aktarım alanı mağazanın raporladığı değeri (müşterinin gerçekte ödediği fiyatı) yansıtırken; kontrol paneli ürünün mevcut fiyatını yansıtır. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Teklif Türü, Teklif Kimliği, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Dönem, Yenileme Durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif Kimliği, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [MRR](mrr) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: mrr --- --- title: "MRR" description: "Adapty'de Aylık Yinelenen Geliri (MRR) anlayın ve optimize edin." --- Aylık Yinelenen Gelir (MRR) grafiği, aktif ücretli aboneliklerinizden elde edilen geliri aylık bir rakama normalize ederek gösterir. Abonelik süresinden bağımsız olarak abonelik işinizin ürettiği istikrarlı geliri yansıtır. Her abone kohortunun yinelenen gelire zaman içinde nasıl katkıda bulunduğunu görmek için grafiği ilk satın alma ayına göre gruplandırın ve aylık çözünürlüğe geçin. Yığılmış alan görünümü, her kohortun ay ay katkısını ortaya koyar. ## Hesaplama \{#calculation\} :::warning Aşağıdaki hesap makinesi mağaza komisyonu ve vergilendirmeyi [dikkate almamaktadır](how-adapty-analytics-works#commissions-and-taxes). Sonucu **brüt gelir** hesaplamalarınızla karşılaştırın. ::: MRR, her aboneliğin gelirini aylık eşdeğerine normalize eder — yıllık 240 dolarlık bir abonelik, 240 dolar peşin değil, her ay 20 dolar katkı sağlar. Bu sayede MRR, abonelik faturalama dönemleri nasıl dağıtılırsa dağıtılsın istikrarlı kalır. MRR, tüm abonelik türlerinizde (fiyat × aktif aboneler ÷ aylık faturalandırma dönemi) toplamıdır. Haftalık abonelikler için faturalandırma dönemi yaklaşık 0,23 ay olarak kullanılır. <SimpleCalculator client:load heading="MRR" formuLatex="\sum_{subscriptions}^{}\frac{P_s\times N_s}{D_m}" variables={[ { nameInTheFormula: "P_s", variableName: "subscriptionPrice", variableDescription: "Fiyat", variableValue: 10 }, { nameInTheFormula: "N_s", variableName: "activeSubs", variableDescription: "Aboneler", variableValue: 1, isInteger: true }, { nameInTheFormula: "D_m", variableName: "duration", variableDescription: "Abonelik dönemi", variableValue: 1, options: [ { label: "Haftalık", value: 0.23 }, { label: "Aylık", value: 1 }, { label: "2 ay", value: 2 }, { label: "3 ay", value: 3 }, { label: "6 ay", value: 6 }, { label: "Yıllık", value: 12 } ] } ]} formulaCalculation="(subscriptionPrice * activeSubs) / duration" isSum={true} defaultRows={[ { subscriptionPrice: 240, activeSubs: 2, duration: 12}, { subscriptionPrice: 30, activeSubs: 10, duration: 1}, { subscriptionPrice: 10, activeSubs: 20, duration: 0.23}, ]} /> MRR, yinelenen gelir üretmeyen ürünleri hesaba katmaz: - tek seferlik satın almalar - consumable'lar - yenilenmez abonelikler Kullanıcı tabanınız tek seferlik ürünler aracılığıyla düzenli gelir elde edebilir. Ancak bu gelir, satın almaların kendisi yinelenmediği için MRR'a dahil edilmez. ## İade işleme \{#refund-handling\} Bir abonelik iade edildiğinde, MRR daha önce sayıldığı grafikteki her tarihten bu aboneliğin katkısını çıkarır. Geçmiş MRR değerleri, bir iade gerçekleştikten sonra düşebilir. Metrikler genelinde tam karşılaştırma için bkz. [Metrikler iadeleri nasıl işler](refund-events#how-metrics-handle-refunds). ## Para Birimi \{#currency\} Adapty tüm parasal grafikleri, orijinal işlem para biriminden bağımsız olarak **ABD doları** cinsinden görüntüler. Bu durum; Gelir, MRR, ARR, ARPU, ARPPU, LTV, tahmin edilen gelir, iade tutarları ve kohort ile A/B testi raporlarındaki gelir rakamlarını kapsar. Başka bir para biriminde görüntüleme ayarı mevcut değildir. Adapty, her işlemi [currencylayer.com](https://currencylayer.com/) üzerinden her 8 saatte bir yenilenen ve **işlem anında sabitlenen** bir kur üzerinden ABD dolarına çevirir. Geçmiş USD değerleri, kur değişimlerinde yeniden hesaplanmaz. Yerel para birimi değerlerine işlem bazında şu yerlerden ulaşabilirsiniz: - Webhook'lardaki `price_local` ve `currency` alanları - S3, GCS ve BigQuery dışa aktarımlarındaki `_local` sütunları (örneğin `revenue_local` ve `proceeds_local`) ve `currency` - Profil sayfası (işlem bazında görünüm) Yerel para biriminde finans raporlaması yapmak için, dışa aktarımdan işlem bazındaki yerel para birimi değerlerini alıp kendiniz toplamanız gerekir. ## Yenileme fiyatlandırması \{#renewal-pricing\} Adapty, yenileme gelirini ürünün mevcut fiyatı üzerinden hesaplar; bu, aboneliğe ilk kaydolduklarında önceki bir fiyattan yararlanan kullanıcılar için de geçerlidir. App Store Connect veya Google Play'de fiyatı değiştirmenizin ardından, mevcut aboneler için kontrol panelindeki Revenue, MRR ve ARR rakamları gerçekte tahsil edilen gelirden sapabilir — Adapty, mağazanın bu kullanıcıları eski fiyatta tutmuş olmasına rağmen yeni fiyatı uygular. Doğrulamak için, aynı işlemler üzerinde S3, GCS veya BigQuery dışa aktarımındaki işlem başına `price` alanını kontrol paneliyle karşılaştırın. Dışa aktarım alanı mağazanın raporladığı değeri (müşterinin gerçekte ödediği fiyatı) yansıtırken; kontrol paneli ürünün mevcut fiyatını yansıtır. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Teklif Türü, Teklif ID'si, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Dönem, Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID'si, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Revenue](revenue) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: arr --- --- title: "ARR" description: "Yıllık Yinelenen Geliri (ARR) takip edin ve abonelik stratejinizi optimize edin." --- Yıllık Yinelenen Gelir grafiği, tüm aktif otomatik yenilenen aboneliklerden elde edilen geliri bir yıla normalize ederek gösterir. Grafik, ödeme yapılmış ve süresi dolmamış her aboneliği aktif kabul eder. ARR, abonelik işinizin büyümesini takip etmek ve gelecekteki geliri tahmin etmek için kritik bir metriktir. ## Hesaplama \{#calculation\} :::warning Aşağıdaki hesap makinesi [mağaza komisyonu ve vergilendirmeyi](how-adapty-analytics-works#commissions-and-taxes) **dikkate almaz**. Sonucu **brüt gelir** hesaplamalarınızla karşılaştırın. ::: ARR, yinelenen abonelik gelirinizin yıllık bazda ifade edilmiş halidir. En çok yıllık aboneliklerin temel ürün olduğu durumlarda işe yarar; ağırlıklı olarak aylık veya haftalık aboneliklere sahip işletmeler için [MRR](mrr) daha bilgilendirici olacaktır. ARR, tüm abonelik türleriniz için (fiyat × aktif aboneler ÷ yıl cinsinden faturalama dönemi) toplamıdır. Aylık için 1/12, haftalık için 1/52 kullanın. <SimpleCalculator client:load heading="ARR" formuLatex="\sum \frac{P_s \times U_s}{D_y}" variables={[ { nameInTheFormula: "P_s", variableName: "price", variableDescription: "Abonelik fiyatı", variableValue: 240 }, { nameInTheFormula: "U_s", variableName: "subs", variableDescription: "Aktif ücretli aboneler", variableValue: 2, isInteger: true }, { nameInTheFormula: "D_y", variableName: "periods", variableDescription: "Abonelik dönemi", variableValue: 1, options: [ { label: "Haftalık", value: "1/52" }, { label: "Aylık", value: "1/12" }, { label: "2 ay", value: "2/12" }, { label: "3 ay", value: "3/12" }, { label: "6 ay", value: "6/12" }, { label: "Yıllık", value: 1 } ] } ]} formulaCalculation="(price * subs ) / periods" isSum={true} defaultRows={[ { price: 240, subs: 2, periods: "1" }, { price: 30, subs: 10, periods: "1/12" }, { price: 10, subs: 20, periods: "1/52" } ]} /> ## İade işleme \{#refund-handling\} Bir abonelik iade edildiğinde, ARR o aboneliğin daha önce sayıldığı grafikteki her tarihten katkısını kaldırır. Geçmiş ARR değerleri, bir iade gerçekleştikten sonra düşebilir. Metriklerin iadeleri nasıl ele aldığına dair tam karşılaştırma için bkz. [Metrikler iadeleri nasıl işler](refund-events#how-metrics-handle-refunds). ## Para Birimi \{#currency\} Adapty tüm parasal grafikleri, orijinal işlem para biriminden bağımsız olarak **ABD doları** cinsinden görüntüler. Bu durum; Gelir, MRR, ARR, ARPU, ARPPU, LTV, tahmin edilen gelir, iade tutarları ve kohort ile A/B testi raporlarındaki gelir rakamlarını kapsar. Başka bir para biriminde görüntüleme ayarı mevcut değildir. Adapty, her işlemi [currencylayer.com](https://currencylayer.com/) üzerinden her 8 saatte bir yenilenen ve **işlem anında sabitlenen** bir kur üzerinden ABD dolarına çevirir. Geçmiş USD değerleri, kur değişimlerinde yeniden hesaplanmaz. Yerel para birimi değerlerine işlem bazında şu yerlerden ulaşabilirsiniz: - Webhook'lardaki `price_local` ve `currency` alanları - S3, GCS ve BigQuery dışa aktarımlarındaki `_local` sütunları (örneğin `revenue_local` ve `proceeds_local`) ve `currency` - Profil sayfası (işlem bazında görünüm) Yerel para biriminde finans raporlaması yapmak için, dışa aktarımdan işlem bazındaki yerel para birimi değerlerini alıp kendiniz toplamanız gerekir. ## Yenileme fiyatlandırması \{#renewal-pricing\} Adapty, yenileme gelirini ürünün mevcut fiyatı üzerinden hesaplar; bu, aboneliğe ilk kaydolduklarında önceki bir fiyattan yararlanan kullanıcılar için de geçerlidir. App Store Connect veya Google Play'de fiyatı değiştirmenizin ardından, mevcut aboneler için kontrol panelindeki Revenue, MRR ve ARR rakamları gerçekte tahsil edilen gelirden sapabilir — Adapty, mağazanın bu kullanıcıları eski fiyatta tutmuş olmasına rağmen yeni fiyatı uygular. Doğrulamak için, aynı işlemler üzerinde S3, GCS veya BigQuery dışa aktarımındaki işlem başına `price` alanını kontrol paneliyle karşılaştırın. Dışa aktarım alanı mağazanın raporladığı değeri (müşterinin gerçekte ödediği fiyatı) yansıtırken; kontrol paneli ürünün mevcut fiyatını yansıtır. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtrele: Attribution, Kitle, Ülke, Teklif Türü, Teklif ID, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Grupla: Dönem, Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Gelir](revenue) - [MRR](mrr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: arpu --- --- title: "ARPU" description: "Kullanıcı başına ortalama geliri (ARPU) analiz ederek gelir optimizasyonu yapın." --- ARPU (kullanıcı başına ortalama gelir) grafiği, belirli bir dönemde kullanıcı başına elde edilen ortalama geliri gösterir. Bu metrik, bir kohortun toplam gelirinin o kohortun kullanıcı sayısına bölünmesiyle hesaplanır. ARPU'yu; attribution kaynağı, ülke veya ürün gibi kullanıcı segmentleri arasında gelir performansını karşılaştırmak için kullanabilirsiniz. ## Hesaplama \{#calculation\} :::warning Aşağıdaki hesap makinesi [mağaza komisyonu ve vergilendirmeyi](how-adapty-analytics-works#commissions-and-taxes) **dikkate almaz**. Sonucu **brüt gelir** hesaplamalarınızla karşılaştırın. ::: ARPU, uygulamanızın kullanıcı başına ürettiği ortalama geliri gösterir; monetizasyon verimliliği için yaygın kullanılan bir kıyaslama ölçütüdür. ARPU, dönem gelirinizin (iadeler düşüldükten sonra) o dönemdeki toplam uygulama kullanıcı sayısına bölünmesiyle hesaplanır. <CompoundCalculator client:load heading="ARPU" formuLatex="\frac{\sum P_i \times Q_i - D}{U_p}" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "Ürün fiyatı", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "Satın alınan ürünler", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "İade edilen tutar", variableValue: 35, global: true }, { nameInTheFormula: "Up", variableName: "users", variableDescription: "Toplam kullanıcı", variableValue: 160, global: true, isInteger: true } ]} rowFormula="price * qty" resultFormula="(_sum - refunds) / users" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## İade işleme \{#refund-handling\} İadeler, işlendiği tarihte gelir paydasından düşülür. Metrikler arasındaki tam karşılaştırma için bkz. [Metriklerin iadeleri nasıl işlediği](refund-events#how-metrics-handle-refunds). ## Para Birimi \{#currency\} Adapty tüm parasal grafikleri, orijinal işlem para biriminden bağımsız olarak **ABD doları** cinsinden görüntüler. Bu durum; Gelir, MRR, ARR, ARPU, ARPPU, LTV, tahmin edilen gelir, iade tutarları ve kohort ile A/B testi raporlarındaki gelir rakamlarını kapsar. Başka bir para biriminde görüntüleme ayarı mevcut değildir. Adapty, her işlemi [currencylayer.com](https://currencylayer.com/) üzerinden her 8 saatte bir yenilenen ve **işlem anında sabitlenen** bir kur üzerinden ABD dolarına çevirir. Geçmiş USD değerleri, kur değişimlerinde yeniden hesaplanmaz. Yerel para birimi değerlerine işlem bazında şu yerlerden ulaşabilirsiniz: - Webhook'lardaki `price_local` ve `currency` alanları - S3, GCS ve BigQuery dışa aktarımlarındaki `_local` sütunları (örneğin `revenue_local` ve `proceeds_local`) ve `currency` - Profil sayfası (işlem bazında görünüm) Yerel para biriminde finans raporlaması yapmak için, dışa aktarımdan işlem bazındaki yerel para birimi değerlerini alıp kendiniz toplamanız gerekir. ## Kullanılabilir filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme: Attribution, Ülke, A/B testi, Segment ve Mağaza. - ✅ Gruplama: Ülke, Mağaza, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Revenue](revenue) - [MRR](mrr) - [ARPPU](arppu) - [ARR](arr) --- # File: arppu --- --- title: "ARPPU" description: "ARPPU'yu (Ödeme Yapan Kullanıcı Başına Ortalama Gelir) ve uygulamanızın monetizasyonuna etkisini anlayın." --- Ödeme yapan kullanıcı başına ortalama gelir (ARPPU) grafiği, ödeme yapan kullanıcı başına ortalama geliri gösterir. Ödeme yapan müşterilerin oluşturduğu gerçek gelirin, iadeler düşüldükten sonra müşteri sayısına bölünmesiyle hesaplanır. Hangi edinim kanallarının daha yüksek değerli ödeme yapan kullanıcılar getirdiğini görmek için ARPPU'yu attribution'a göre gruplandırın. ## Hesaplama \{#calculation\} :::warning Aşağıdaki hesap makinesi [mağaza komisyonu ve vergilendirmeyi](how-adapty-analytics-works#commissions-and-taxes) **dikkate almaz**. Sonucu **brüt gelir** hesaplamalarınızla karşılaştırın. ::: ARPPU, ödeme yapan kullanıcı başına ortalama geliri gösterir — ödeme yapmayan kullanıcılar paydadan çıkarıldığından genellikle [ARPU](arpu)'dan çok daha yüksektir. ARPPU, dönemin gelirinin (iadeler düşüldükten sonra) o dönemdeki ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. <CompoundCalculator client:load heading="ARPPU" formuLatex="\frac{\sum P_i \times Q_i - D}{U_p}" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "Ürün fiyatı", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "Satın alınan ürünler", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "İade edilen tutar", variableValue: 35, global: true }, { nameInTheFormula: "Up", variableName: "users", variableDescription: "Ödeme yapan kullanıcılar", variableValue: 16, global: true, isInteger: true } ]} rowFormula="price * qty" resultFormula="(_sum - refunds) / users" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## İade işleme \{#refund-handling\} İadeler, işlendiği tarihte gelir payından düşülür. Satın alması daha sonra iade edilen bir kullanıcı, ödeme yapan kullanıcılar paydasında sayılmaya devam eder; bu nedenle yoğun iadeler ARPPU'yu beklenenden daha hızlı düşürür. Metrikler genelinde tam karşılaştırma için bkz. [Metrikler iadeleri nasıl ele alır](refund-events#how-metrics-handle-refunds). ## Para Birimi \{#currency\} Adapty tüm parasal grafikleri, orijinal işlem para biriminden bağımsız olarak **ABD doları** cinsinden görüntüler. Bu durum; Gelir, MRR, ARR, ARPU, ARPPU, LTV, tahmin edilen gelir, iade tutarları ve kohort ile A/B testi raporlarındaki gelir rakamlarını kapsar. Başka bir para biriminde görüntüleme ayarı mevcut değildir. Adapty, her işlemi [currencylayer.com](https://currencylayer.com/) üzerinden her 8 saatte bir yenilenen ve **işlem anında sabitlenen** bir kur üzerinden ABD dolarına çevirir. Geçmiş USD değerleri, kur değişimlerinde yeniden hesaplanmaz. Yerel para birimi değerlerine işlem bazında şu yerlerden ulaşabilirsiniz: - Webhook'lardaki `price_local` ve `currency` alanları - S3, GCS ve BigQuery dışa aktarımlarındaki `_local` sütunları (örneğin `revenue_local` ve `proceeds_local`) ve `currency` - Profil sayfası (işlem bazında görünüm) Yerel para biriminde finans raporlaması yapmak için, dışa aktarımdan işlem bazındaki yerel para birimi değerlerini alıp kendiniz toplamanız gerekir. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Dönem, Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Revenue](revenue) - [MRR](mrr) - [ARPU](arpu) - [ARR](arr) --- # File: installs --- --- title: "Kurulumlar" description: "Uygulama kurulumlarını takip edin ve abonelikler üzerindeki etkilerini Adapty ile anlayın." --- Kurulumlar grafiği, seçilen dönemde uygulamanızı kaç kullanıcının kurduğunu gösterir. Neyin kurulum sayılacağı ve her kurulumun nasıl gruplandırılacağı, kurulum sayma ayarına bağlıdır. Bu makale, uygun bir sayım modunun nasıl seçileceğini ve farklı analitik kaynakları arasındaki [olası tutarsızlıkların nasıl giderileceğini](#troubleshooting) açıklar. ## Kurulum olarak ne sayılır \{#what-counts-as-an-install\} Adapty SDK, kullanıcı uygulamanızı ilk kez başlattığında bir "kurulum" kaydeder ve bunu Adapty'ye gönderir. Bunun iki sonucu vardır: - Kullanıcı uygulamayı ilk kez açtığında Adapty'de bir kurulum görünür; bu, uygulamayı indirdikten saatler veya günler sonra olabilir. - Kullanıcı uygulamayı indirip hiç açmazsa Adapty onu saymaz. **App Settings** içindeki **raporlama saat diliminiz**, her kurulumun hangi güne ait sayılacağını belirler. UTC ile 1 Haziran 23:30'da gerçekleşen bir kurulum, raporlama saat diliminiz +02:00 ise 2 Haziran'a düşer; App Store Connect veya Google Play ise bunu 1 Haziran olarak gösterebilir. ### Sayım modları \{#counting-modes\} **Installs definition for analytics** ayarı, yeni bir yüklemenin nasıl sayılacağını belirler. Değiştirmek için [App Settings → General → Installs definition for analytics](general#4-installs-definition-for-analytics) sayfasını açın. | Mod | Ne sayılır | Örnek | Üçüncü taraf metriği | Olası farklılıklar | | --- | --- | --- | --- | --- | | **Yeni device_id'ler** (önerilen) | **Her uygulama kurulumu** — yeniden kurulumlar dahil. Kimlik doğrulama, profil oluşturma ve sürüm yükseltmeleri sayıya eklenmez. | 5 cihazda bir kullanıcı = 5 kurulum. <br /> <br /> Aynı cihazda yeniden kurulum = 2 kurulum. | App Store: <br /> **Total Active Devices** <br /> <br /> Google Play: **Devices** | Yeniden kurulumlar yaygınsa **uygulama indirme sayısından yüksek** olur. <br /> <br /> Birçok kullanıcı uygulamayı açmadan indiriyorsa **uygulama indirme sayısından düşük** olur. | | **Yeni customer_user_id'ler** | Yalnızca [kimliği tanımlanmış kullanıcı](identifying-users) başına **ilk kurulum** sayılır. Ek cihazlar ve anonim kullanıcılar sayıya dahil edilmez. | 5 cihazda bir kullanıcı = 1 kurulum. <br /> <br /> Yeniden kurulum, tekrar giriş = yeni kurulum yok. <br /> <br /> Hesap olmadan uygulamayı kullanma = yeni kurulum yok. | Uygulamanızın kimlik doğrulama sisteminden kayıt istatistikleri | Kullanıcıları hiç tanımlamıyorsanız **boş kalır**. | | **Adapty'deki yeni profiller** (eski) | Her kurulum ve yeniden kurulumu sayar; **oturumu kapatınca oluşturulan anonim profiller de dahildir**. | Bir kullanıcı, bir cihaz, 3 oturum kapatma = 4 kurulum. | Yok | **Tüm harici metriklerden yüksek**. Oturumu kapatınca oluşturulan her anonim profili kurulum olarak sayar. | Özellikle bir nedeniniz yoksa **New device_ids** kullanın. ## Sorun Giderme \{#troubleshooting\} ### Adapty'nin sayısı App Store Connect veya Google Play'den yüksek \{#adaptys-count-is-higher-than-app-store-connect-or-google-play\} Bunun iki olası nedeni vardır: - **Yeniden yüklemeler.** [Sayım modunuz](#counting-modes) **New device_ids** olarak ayarlanmışsa, Adapty hem ilk açılışları hem de sonraki yeniden yüklemeleri sayar. App Store Connect'in "Total Downloads" metriği ise yalnızca ilk indirmeyi hesaba katar. - **İlk açılış tarihi ≠ indirme tarihi.** Mağazalar indirme tarihine göre ilişkilendirir. Uygulamayı geç açan kullanıcılar farklı günlere düşer. Daha temiz bir karşılaştırma için **App Store Connect → Total Active Devices** veya **Google Play → Devices** bölümünü açın. Bu metrikler cihaz düzeyindedir ve Adapty'nin **New device_ids** moduna daha yakındır. ### Adapty'nin sayısı sıfır \{#adaptys-count-is-zero\} Sayım modunuz **New customer_user_ids** ise, ancak kullanıcıları <InlineTooltip tooltip="kullanıcıları doğrulamıyorsanız">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Unity](unity-identifying-users), [Kotlin Multiplatform](kmp-quickstart-identify), [Capacitor](capacitor-quickstart-identify)</InlineTooltip> Bu modda Adapty hiçbir kurulumu kaydetmez; anonim kurulumlar hariç tutulur. **New device_ids** moduna geçin ya da kullanıcı kimlik doğrulamasını uygulayın. ### Adapty'nin sayısı AppsFlyer veya Adjust'tan farklı \{#adaptys-count-differs-from-appsflyer-or-adjust\} MMP'ler kurulumları kendi SDK başlatma veya ilk temas olaylarına göre ilişkilendirir. Bunlar, Adapty'nin ilk SDK başlatmasından farklı bir zamanda tetiklenir — bu yüzden belirli bir fark normal karşılanmalıdır. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Ülke, A/B testi, Segment ve Mağaza. - ✅ Gruplama ölçütleri: Ülke, Mağaza, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#subscribers-and-conversion) bakın. - [Yeni abonelikler](reactivated-subscriptions) - [Aktif abonelikler](active-subscriptions) - [Yeni denemeler](new-trials) --- # File: active-subscriptions --- --- title: "Aktif abonelikler" description: "Adapty'nin güçlü analitiğiyle aktif abonelikleri izleyin ve yönetin." --- Aktif abonelikler grafiği, seçilen her dönemin sonunda henüz süresi dolmamış benzersiz ücretli aboneliklerin sayısını gösterir. Başlayıp hâlâ aktif olan normal (süresi dolmamış) uygulama içi abonelikleri kapsar; ücretsiz deneme sürümlerini ve yenilemesi iptal edilmiş abonelikleri dışarıda bırakır. Abone tabanınızın büyüklüğü ve büyümesi için bir gösterge niteliği taşır. ## Hesaplama \{#calculation\} Aktif abonelikler metriği, her dönemin sonunda ücretli ve süresi dolmamış abonelikleri sayar. Ek süresi olmayan abonelikler için, bir sonraki yenileme tarihi başarılı bir yenileme gerçekleşmeden geçtiğinde abonelik sona erer. Örneğin: Geçen ayın sonunda 500 aktif abonelik, bu ay eklenen 50 yeni abonelik ve bu ay sona eren 25 abonelik = bu ayın sonunda 525 aktif abonelik. ## İade işleme \{#refund-handling\} Bir abonelik iade edildiğinde, Adapty onu aktif sayımdan çıkarır — hem anlık olarak hem de geçmiş tarihler için geriye dönük şekilde. Metrikler genelinde tam karşılaştırma için [Metrikler iadeleri nasıl ele alır](refund-events#how-metrics-handle-refunds) bölümüne bakın. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Teklif Türü, Teklif Kimliği, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Dönem, Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif Kimliği, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#subscribers-and-conversion) bakın. - [Kaybedilen (süresi dolmuş) abonelikler](churned-expired-subscriptions) - [İptal edilen abonelikler](cancelled-subscriptions) - [Abonelik dışı ürünler](non-subscriptions) --- # File: reactivated-subscriptions --- --- title: "Yeni abonelikler" description: "İlk kez dönüşümleri ve ücretsiz deneme ücretli dönüşümlerini izlemek için Adapty'de yeni abonelikleri takip edin." --- **Yeni abonelikler** grafiği, uygulamanızdaki yeni (ilk kez etkinleştirilen) aboneliklerin sayısını gösterir. Bu metrik, belirli bir zaman diliminde başlayan yeni aboneliklerin sayısını gösterir; sıfırdan başlayan abonelikler ve ücretli aboneliğe dönüşen ücretsiz denemeler de dahildir. Abonelik yenilemelerini veya yeniden başlatılan abonelikleri kapsamaz. ## Hesaplama \{#calculation\} Yeni abonelikler metriği, dönem içindeki ilk kez gerçekleşen abonelik aktivasyonlarını sayar — hem sıfırdan başlayan abonelikler hem de ücretli aboneliğe dönüşen ücretsiz denemeler bu kapsama girer. ## Geri ödeme işleme \{#refund-handling\} Yeni abonelikler, geri ödemeleri **düşmez** — sayım, sonradan iade edilen abonelikleri de kapsar. Net etkiyi ölçmek için [Geri ödeme olayları](refund-events) ile karşılaştırın. Metriklerin geri ödemeleri nasıl işlediğine ilişkin tam karşılaştırma için bkz. [Metrikler geri ödemeleri nasıl işler](refund-events#how-metrics-handle-refunds). ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontroller](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtrele: Attribution, Kitle, Ülke, Teklif Türü, Teklif ID'si, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Grupla: Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID'si, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#subscribers-and-conversion) bakın. - [Aktif abonelikler](active-subscriptions) - [Sonlanan (süresi dolan) abonelikler](churned-expired-subscriptions) - [İptal edilen abonelikler](cancelled-subscriptions) - [Abonelik dışı ürünler](non-subscriptions) --- # File: non-subscriptions --- --- title: "Abonelik Olmayan Ürünler" description: "Adapty'de abonelik olmayan ürünleri nasıl yöneteceğinizi ve kullanıcı satın alımlarını nasıl verimli şekilde takip edeceğinizi öğrenin." --- Abonelik Olmayan Ürünler grafiği, otomatik yenilenen abonelik olmayan uygulama içi satın alımları sayar: consumable, non-consumable ve yenilenmez abonelikler. Yenilemeler bu grafiğe dahil edilmez. :::note "Abonelik olmayanlar", "tek seferlik satın almalar"dan daha geniş bir kavramdır — consumable'lar ve yenilenmez abonelikler birden fazla kez satın alınabilir. ::: ## Hesaplama \{#calculation\} Her abonelik olmayan uygulama içi satın alma, üç türden birine girer: - **Consumable'lar**: Kullanıcıların birden fazla kez satın alabileceği öğeler; örneğin bir balıkçı uygulamasındaki balık yemi veya oyun içi ekstra para birimi. - **Non-consumable'lar**: Kullanıcıların bir kez satın alıp sonsuza kadar kullandığı öğeler; örneğin bir oyun uygulamasındaki yarış pisti veya reklamsız sürüm. - **Yenilenmez abonelikler**: Belirli bir sürenin ardından sona eren ve otomatik olarak yenilenmeyen abonelikler; örneğin bir içerik kataloğuna bir yıllık erişim. İçerik sabit kalabilir ancak abonelik süresi dolduğunda yenilenmez. :::note Bu grafik yalnızca satın alma olaylarını sayar ve iade edilen satın almaları düşmez. Sık sık iade edilen abonelik dışı ürünleriniz varsa, gösterilen sayı gelir oluşturan gerçek satın alma sayısından yüksek olabilir. ::: ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Segment, Mağaza ve Ürün. - ✅ Gruplama ölçütleri: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Aktif abonelikler](active-subscriptions) - [Yeni abonelikler](reactivated-subscriptions) - [Kaybedilen (süresi dolan) abonelikler](churned-expired-subscriptions) - [İptal edilen abonelikler](cancelled-subscriptions) --- # File: cancelled-subscriptions --- --- title: "İptal edilen abonelik yenilemeleri" description: "Adapty'nin yönetim araçlarıyla iptal edilen abonelikleri verimli şekilde yönetin." --- Abonelik yenileme iptalleri grafiği, otomatik yenileme durumu kapatılmış (kullanıcı tarafından iptal edilmiş) aboneliklerin sayısını gösterir. Bir aboneliğin otomatik yenileme durumu kapatıldığında, abonelik bir sonraki dönem için otomatik olarak yenilenmez. Ancak kullanıcı, mevcut dönemin sonuna kadar uygulamanın premium özelliklerine erişmeye devam eder. ## Hesaplama \{#calculation\} Abonelik yenileme iptalleri metriği, belirtilen dönem içinde otomatik yenilemesi kapatılan abonelikleri sayar. Kullanıcı mevcut fatura dönemi bitene kadar premium erişimini korur, ancak bu süreden sonra abonelik otomatik olarak yenilenmez. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtrele: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Grupla: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için bkz. [Metrik karşılaştırma tablosu](metric-comparison-table#churn). - [Aktif abonelikler](active-subscriptions) - [Kaybedilen (süresi dolmuş) abonelikler](churned-expired-subscriptions) - [Yeni abonelikler](reactivated-subscriptions) - [Abonelik dışı ürünler](non-subscriptions) --- # File: churned-expired-subscriptions --- --- title: "Sonlanan (süresi dolmuş) abonelikler" description: "Kullanıcı tutma oranını artırmak için sonlanan ve süresi dolmuş abonelikleri yönetin." --- Kaybedilen (süresi dolan) abonelikler grafiği, süresi dolmuş aboneliklerin sayısını gösterir; yani kullanıcı artık uygulamanın premium özelliklerine erişemez. Bu durum genellikle kullanıcının abonelik döneminin sonunda ödemeyi durdurmaya karar vermesi ya da bir ödeme sorunuyla karşılaşması sonucunda ortaya çıkar. Gönüllü kaybı, ödeme kaynaklı kayıptan ayırt etmek için sona erme nedenine göre gruplandırın. ## Hesaplama \{#calculation\} Kaybedilen (süresi dolmuş) abonelikler metriği, belirtilen dönemde süresi dolan abonelikleri sayar; yani kullanıcıların premium özelliklere erişimini kaybettiği durumları kapsar. Bu metrik, yenilemeyi tercih etmeyen kullanıcıları da ödeme sorunu nedeniyle aboneliğini kaybedenleri de içerir. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtrele: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Grupla: Sona erme nedeni, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#churn) bakın. - [Aktif abonelikler](active-subscriptions) - [Yeni abonelikler](reactivated-subscriptions) - [İptal edilen abonelikler](cancelled-subscriptions) - [Abonelik dışı satın almalar](non-subscriptions) --- # File: active-trials --- --- title: "Aktif denemeler" description: "Adapty analitiği ile aktif abonelik denemelerini takip edin ve yönetin." --- Adapty'deki aktif denemeler grafiği, belirli bir dönemin sonunda hâlâ aktif olan, süresi dolmamış ücretsiz deneme sayısını gösterir. Aktif, henüz süresi dolmamış abonelikler anlamına gelir; dolayısıyla kullanıcılar uygulamanın ücretli özelliklerine erişmeye devam eder. ## Hesaplama \{#calculation\} Aktif deneme metriki, her dönemin sonundaki süresi dolmamış ücretsiz denemeleri sayar. Otomatik yenilemeyi iptal etmek, bir denemeyi sayıdan çıkarmaz — yalnızca süresinin dolması çıkarır. Örneğin: Dün 100 aktif deneme, bugün eklenen 10 yeni deneme, bugün süresi dolan 5 deneme = bugün 105 aktif deneme. ## Kullanılabilir filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Teklif Türü, Teklif ID, Teklif İndirim Türü, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Dönem, Yenileme durumu, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#subscribers-and-conversion) bakın. - [Yeni denemeler](new-trials) - [Deneme yenilemesi iptal edildi](trials-renewal-cancelled) - [Süresi dolmuş denemeler](expired-churned-trials) --- # File: new-trials --- --- title: "Yeni denemeler" description: "Yeni abonelik denemelerini yönetin ve deneme-ödeme dönüşüm oranlarını optimize edin." --- Yeni denemeler grafiği, seçilen zaman diliminde etkinleştirilen deneme sayısını gösterir. Reklam kampanyaları ve diğer kullanıcı edinme çalışmalarından gelen deneme hacmini takip etmek için kullanabilirsiniz. ## Hesaplama \{#calculation\} Yeni denemeler metriği, dönem sonunda hâlâ aktif olup olmadıklarına bakılmaksızın, o dönemde başlayan denemeleri sayar. Örneğin, Mayıs'ta 50 kullanıcı deneme başlatırsa, grafiği ne zaman görüntülediğinizden bağımsız olarak Mayıs veri noktası 50 gösterir; bazıları zaten sona ermiş ya da ücretli aboneliğe dönüşmüş olsa bile. ## Kullanılabilir filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Teklif Türü, Teklif ID'si, Teklif İndirim Türü, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID'si, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#subscribers-and-conversion) bakın. - [Aktif denemeler](active-trials) - [Deneme yenileme iptali](trials-renewal-cancelled) - [Süresi dolmuş denemeler](expired-churned-trials) --- # File: trials-renewal-cancelled --- --- title: "Deneme süresi yenilemesi iptal edildi" description: "Adapty'nin içgörüleriyle deneme süresi yenilemelerini, iptalleri ve abonelik akışlarını anlayın." --- Trials renewal cancelled grafiği, yenilemesi iptal edilmiş (kullanıcı tarafından iptal edilen) deneme sürelerinin sayısını gösterir. Deneme süresi yenilemesi devre dışı bırakıldığında, bu deneme süresi otomatik olarak ücretli aboneliğe dönüştürülmez; ancak kullanıcı mevcut dönem sonuna kadar uygulamanın premium özelliklerini kullanmaya devam edebilir. ## Hesaplama \{#calculation\} Trials renewal cancelled metriği, kullanıcının belirli bir dönem içinde otomatik yenilemeyi kapattığı deneme sürümlerini sayar. Kullanıcı, deneme süresi bitene kadar erişimini korur; ancak deneme süresi sona erdiğinde aboneliğe otomatik olarak dönüşmez. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#churn) bakın. - [Yeni denemeler](new-trials) - [Aktif denemeler](active-trials) - [Süresi dolmuş denemeler](expired-churned-trials) --- # File: expired-churned-trials --- --- title: "Süresi dolmuş (churn) denemeler" description: "Adapty analitiği ile süresi dolmuş ve churn olan denemeleri etkili şekilde yönetin." --- Süresi Dolmuş (churn) Denemeler grafiği, süresi dolarak kullanıcıların uygulamanın premium özelliklerine erişimini kaybettiği denemelerin sayısını gösterir. Çoğu durumda bu, kullanıcıların uygulama için ödeme yapmamaya karar vermesi veya ödeme sorunları yaşamasıyla gerçekleşir. ## Hesaplama \{#calculation\} Süresi dolan denemeler metriği, belirtilen dönemde sona eren deneme sürelerini sayar; yani kullanıcının premium özelliklere erişimi sona ermiştir. Bu, dönüşüm yapmamayı tercih eden kullanıcıları da ödeme sorunu nedeniyle dönüşümü başarısız olanları da kapsar. Gönüllü churn ile ödeme kaynaklı churn'ü birbirinden ayırmak için **Expiration reason** seçeneğiyle gruplayın. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontroller](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Sona erme nedeni, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#churn) bakın. - [Yeni denemeler](new-trials) - [Aktif denemeler](active-trials) - [Deneme yenileme iptalleri](trials-renewal-cancelled) --- # File: refund-events --- --- title: "İade etkinlikleri" description: "Churn'ü azaltmak ve geliri optimize etmek için Adapty'deki iade etkinliklerini yönetin." --- İade etkinlikleri grafiği, kaç satın alma ve aboneliğin iade edildiğini gösterir. Adapty, her iade etkinliğini abonelik başlangıç tarihine değil, iadenin gerçekleştiği tarihe bağlar. ## Hesaplama \{#calculation\} Adapty, seçilen dönem içinde iade edilen her satın alma veya aboneliği sayar. Her iade, aboneliğin başladığı tarihe değil, gerçekleştiği tarihe atfedilir. Deneme süreleri herhangi bir gelir oluşturmadığından, bunlara ait iadeler hesaba katılmaz. ## Metriklerin iadeleri nasıl işlediği \{#how-metrics-handle-refunds\} Farklı metrikler iadeleri farklı şekilde ele alır. Aynı iade olayı bir grafiği anında düşürürken, başka bir grafiği geriye dönük olarak (geçmiş dönem değerlerini değiştirerek) etkileyebilir ya da üçüncü bir grafiği hiç etkilemeyebilir. Aşağıdaki tablo, metrik başına kuralları göstermektedir. | Metrik | İadeler uygulandı mı? | Attribution tarihi | Negatife düşebilir mi? | Notlar | | --- | --- | --- | --- | --- | | [Revenue](revenue) | Evet | İade tarihi — orijinal satın alma tarihi değil | Evet — iadelerin yeni geliri aştığı günlerde | Revenue = toplam işlemler − iadeler. | | [MRR](mrr) | Evet, geriye dönük olarak | Abonelik, aktif olduğu tüm dönemlerden kaldırılır | Hayır | Geçmiş dönem değerleri iade sonrasında düşebilir. | | [ARR](arr) | Evet, geriye dönük olarak | MRR ile aynı | Hayır | Geçmiş dönem değerleri iade sonrasında düşebilir. | | [ARPU](arpu) | Evet | İade tarihi | Evet (iade yoğun dönemlerde) | İadeler, gelir payından düşülür. | | [ARPPU](arppu) | Evet, yalnızca pay | İade tarihi | Evet (iade yoğun dönemlerde) | İadeler, gelir payından düşülür. İade edilen kullanıcı ödeme yapan kullanıcı paydasında sayılmaya devam eder; bu nedenle yoğun iadeler ARPPU'yu beklenenden daha hızlı düşürür. | | [Active subscriptions](active-subscriptions) | Evet, geriye dönük olarak | Abonelik sayımdan kaldırılır | Hayır | | | [New subscriptions](reactivated-subscriptions) | **Hayır** | — | Hayır | Sayıma, sonradan iade edilen abonelikler de dahildir. Net etki için [Refund events](refund-events) ile karşılaştırın. | | [Refund money](refund-money) / [Refund events](refund-events) | İadeler **verinin kendisidir** | İade tarihi | Hayır (her zaman ≥ 0) | | | [Retention](analytics-retention) | **Hayır** | — | Hayır | İade edilen kullanıcılar retention eğrisinde sayılmaya devam eder. Bu durum, aynı kohort için Retention'ın [Active subscriptions](active-subscriptions) veya [Revenue](revenue)'den daha yüksek görünmesine yol açabilir. | | [Cohort revenue](analytics-cohorts) | Evet, kümülatif olarak | İade tarihi | Hayır (kümülatif çıkarmalar kohort gelirini sıfırın altına düşürmez) | İadeler gerçekleştikçe kohort gelirinden düşülür. Diğer kohort metrikleri için bkz. [Kohortlar > İade işleme](analytics-cohorts#refund-handling). | | [Paywall metrics](paywall-metrics) / [A/B test metrics](results-and-metrics) (sayımlar) | **Hayır** | — | Hayır | Bu sayfalardaki Subscribers, Paying Subscribers ve ARPPU sayımları iadeler düşülmeden gösterilir. | | GCS / S3 exports | İade, kendi olay satırı olarak | `event_datetime` = iade zaman damgası | Toplanırken net sütunlar negatife düşebilir | İade satırı `is_refund = true` (S3/GCS) veya `subscription_refunded` olay türünü (webhook) taşır. | ### Negatif Değerler \{#negative-values\} Toplu görünümlerde (Gelir grafiği, dışa aktarmalardaki özel analizler), belirli bir dönem veya gruplama için bir metrik negatif değer gösterebilir; bu durum, o dilimde işlenen iadeler aynı dilimde elde edilen yeni geliri aştığında ortaya çıkar. Bu bir hata değil, sistemin tasarlandığı şekilde çalışmasının doğal bir sonucudur. Örneğin: Bir ülkede Salı günü yeni satın alma yapılmadıysa, ancak o gün eski bir satın alma için 100 $ iade işlendiyse, o ülkenin Salı günü geliri −100 $ olarak görünür. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtrele: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif ID, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Grupla: İade Nedeni, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [Para iadesi](refund-money) - [Faturalandırma sorunu](billing-issue) - [Ek süre](grace-period) --- # File: refund-money --- --- title: "Para iadesi" description: "Adapty'de abonelikler için gelir kaybı olmadan para iadesi işlemini nasıl gerçekleştireceğinizi öğrenin." --- Refund money grafiği, seçilen dönemde iade edilen tutarı gösterir. Adapty her iade olayını gerçekleştiği tarihe bağlar; bu nedenle gelir aynı dönemde azalır. ## Hesaplama \{#calculation\} Adapty yalnızca gelir üreten işlemleri sayar; yeni ücretli abonelikler, yenilemeler ve tek seferlik satın almalar bunlar arasındadır. Gelir üretmeyen ve iade edilemeyen ücretsiz denemeler bu hesaplamanın dışında tutulur. Her iade tutarı işlendiği tarihe bağlıdır, dolayısıyla gelir düşüşü aynı döneme yansır. :::info İade tutarı, mağaza ücreti düşülmeden önce hesaplanır. ::: ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif ID, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama: İade Nedeni, Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Teklif Türü, Teklif İndirim Türü, Teklif ID, Segment ve Attribution. ## İade talebi yönetimi \{#refund-request-management\} Refund saver, Adapty kullanıcılarının Apple App Store'dan gelen iade taleplerini otomasyon aracılığıyla daha verimli bir şekilde yönetmesini sağlar. Süreci kolaylaştırarak hem zaman kazandırır hem de gelir kaybını azaltır. Gerçek zamanlı bildirimler ve uygulanabilir içgörülerle bu araç, Apple'ın yönergelerine uyumu korurken iade taleplerine daha kolay yanıt vermenizi sağlar. [Refund saver](refund-saver) hakkında daha fazla bilgi edinin. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#revenue) bakın. - [İade olayları](refund-events) - [Ödeme sorunu](billing-issue) - [Ek süre](grace-period) --- # File: grace-period --- --- title: "Ek süre" description: "Abonelik ek sürelerinin nasıl çalıştığını anlayın ve kullanıcı tutma oranını artırın." --- Ek süre grafiği, bir [fatura sorunu](billing-issue) nedeniyle ek süre durumuna giren aboneliklerin sayısını gösterir. Bu süre boyunca mağaza aboneden ödeme almaya çalışırken abonelik aktif kalmaya devam eder. Ek süre sona ermeden ödeme başarıyla alınamazsa, abonelik fatura sorunu durumuna girer. ## Hesaplama \{#calculation\} Ek süre metriği, seçilen zaman aralığında ek süreye giren abonelikleri sayar. Ek süre, bir aboneliğin yenileme ödemesi başarısız olduğunda başlar ve haftalık abonelikler için 6 güne, diğer fatura dönemleri için ise 16 güne kadar sürer. Bu pencere içinde ödeme gerçekleşirse abonelik normal şekilde devam eder; gerçekleşmezse abonelik [fatura sorunu](billing-issue) durumuna girer. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#billing-issues-and-revenue-recovery) bakın. - [Para iadesi](refund-money) - [İade olayları](refund-events) - [Ödeme sorunu](billing-issue) --- # File: grace-period-converted --- --- title: "Ek süre dönüşümü" description: "Ek süreye giren ve sona ermeden yenilenen abonelik sayısını takip edin." --- **Grace period converted** grafiği, [ek süre](grace-period) durumuna giren ve bu süre dolmadan başarıyla yenilenen abonelik sayısını gösterir. ### Hesaplama \{#calculation\} Grace period converted grafiği, ek süredeki kullanıcılar için günlük abonelik yenileme sayısını gösterir. Ek süre, ödeme hatası nedeniyle abonelik faturalama sorununa girdiğinde başlar ve belirli bir süre sonra sona erer (haftalık abonelikler için 6 gün, diğer tüm abonelikler için 16 gün) ya da ödeme başarıyla alındığında biter. Grafik, ek süre özelliğinin etkinliği hakkında bilgi sunar ve ödeme işleme veya abonelik yönetimindeki olası sorunların tespit edilmesine yardımcı olabilir. ### Kullanılabilir filtreler \{#available-filters\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif ID'si, Teklif İndirim Türü, Paywall, A/B testleri, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ### Grace period converted grafiğinin kullanımı \{#grace-period-converted-chart-usage\} Ek süre özelliğinin ödeme sorunlu abonelikleri ne kadar etkin bir şekilde kurtardığını izlemek için bu grafiği kullanın. Zaman içindeki dönüşüm eğilimlerini takip ederek ödeme çözüm süreçlerindeki kalıpları belirleyebilir ve ek sürelerde uygulanan ödeme güncelleme akışlarınızdaki veya iletişim stratejilerinizdeki değişikliklerin etkisini değerlendirebilirsiniz. ### Benzer metrikler \{#similar-metrics\} - [Faturalama sorunu](billing-issue) - [Faturalama sorunu dönüşümü](billing-issue-converted) - [Faturalama sorunu dönüşüm geliri](billing-issue-converted-revenue) - [Ek süre](grace-period) - [Ek süre dönüşüm geliri](grace-period-converted-revenue) - [İade tutarı](refund-money) - [İade olayları](refund-events) --- # File: grace-period-converted-revenue --- --- title: "Ek süre dönüşüm geliri" description: "Ek süre dönüşümlerinden elde edilen toplam geliri takip edin." --- **Grace period converted revenue** grafiği, [ek süre dönüşümlerinden](grace-period-converted) elde edilen geliri gösterir: [ek süreye](grace-period) giren ve bu süre dolmadan başarıyla yenilenen aboneliklerden elde edilen geliri ifade eder. ### Hesaplama \{#calculation\} Grace period converted revenue grafiği, ek süredeki kullanıcıların abonelik yenilemelerinden elde edilen günlük geliri gösterir. Ek süre, ödeme başarısızlığı nedeniyle abonelik faturalandırma sorunu durumuna girdiğinde başlar ve belirli bir süre sonunda (haftalık abonelikler için 6 gün, diğer tüm abonelikler için 16 gün) ya da ödeme başarıyla alındığında sona erer. Grafik, ek süre özelliğinin etkinliği hakkında bilgi sunar ve ödeme işleme veya abonelik yönetimindeki olası sorunların tespit edilmesine yardımcı olabilir. ### Mevcut filtreler \{#available-filters\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif Kimliği, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre gruplandır: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ### Grace period converted revenue grafiğinin kullanımı \{#grace-period-converted-revenue-chart-usage\} Ödeme sorunu yaşayan aboneliklerden geri kazanılan geliri takip ederek ek süre özelliğinin finansal etkisini ölçmek için bu grafiği kullanın. Bu sayede ek süre stratejinizin etkinliğini sayısal olarak değerlendirebilir ve ek süreyle ilgili özellik veya iletişimlerin yatırım getirisini ölçebilirsiniz. ### Benzer metrikler \{#similar-metrics\} - [Faturalandırma sorunu](billing-issue) - [Faturalandırma sorunu dönüşümü](billing-issue-converted) - [Faturalandırma sorunu dönüşüm geliri](billing-issue-converted-revenue) - [Ek süre](grace-period) - [Ek süre dönüşümü](grace-period-converted) - [İade tutarı](refund-money) - [İade olayları](refund-events) --- # File: billing-issue --- --- title: "Faturalandırma sorunu" description: "Adapty'nin destek araçlarıyla abonelik faturalandırma sorunlarını çözün." --- Faturalandırma sorunu grafiği, Faturalandırma Sorunu durumuna giren aboneliklerin sayısını gösterir. Bu durum genellikle Apple veya Google gibi mağazaların aboneden ödeme alamaması sonucunda tetiklenir. Bunun nedeni süresi dolmuş bir kredi kartı veya yetersiz bakiye gibi durumlar olabilir. ## Hesaplama \{#calculation\} Ödeme sorunu metriği, belirtilen dönemde ödeme sorunu durumuna giren abonelikleri sayar. Bir abonelik, mağaza (Apple veya Google) yenileme ödemesini işleyemediğinde bu duruma girer — genellikle süresi dolmuş bir kredi kartı veya yetersiz bakiye nedeniyle. Ödeme sorunu durumundayken abonelik aktif değildir. [Ek süre](grace-period) özelliği etkinleştirilmişse abonelik, ek süre ödeme yapılmadan sona erdikten sonra ödeme sorunu durumuna girer. ## Mevcut filtreler ve gruplama \{#available-filters-and-grouping\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ## Benzer metrikler \{#similar-metrics\} Bu metriklerin yan yana karşılaştırması için [Metrik karşılaştırma tablosuna](metric-comparison-table#billing-issues-and-revenue-recovery) bakın. - [Fatura sorunu dönüşümü](billing-issue-converted) - [Fatura sorunu dönüşüm geliri](billing-issue-converted-revenue) - [İade tutarı](refund-money) - [İade olayları](refund-events) - [Ek süre](grace-period) - [Ek süre dönüşümü](grace-period-converted) - [Ek süre dönüşüm geliri](grace-period-converted-revenue) --- # File: billing-issue-converted --- --- title: "Faturalandırma sorunu çözüldü" description: "Faturalandırma döngüsü bitmeden çözülen faturalandırma sorunlarının sayısını takip edin." --- Billing issue converted grafiği, [Faturalandırma Sorunu](billing-issue) durumuna giren ve faturalandırma döngüsü sona ermeden yenilenen aboneliklerin günlük sayısını gösterir. ### Hesaplama \{#calculation\} Billing issue converted grafiği, mevcut fatura döngüsünde [Faturalandırma Sorunu](billing-issue) durumuna giren ve o gün yenilenen aboneliklerin sayısını gösterir. Bir abonelik, mağazanın (ör. Apple, Google) süresi dolmuş kredi kartı veya yetersiz bakiye gibi nedenlerle aboneden ödeme alamaması durumunda Faturalandırma Sorunu durumuna girer. Faturalandırma Sorunu durumunda abonelik aktif sayılmaz; mağaza ayarlarında Ek Süre özelliği etkinse abonelik, ek süre dolmadan Faturalandırma Sorunu durumuna geçmez. ### Mevcut filtreler \{#available-filters\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Şuna göre filtrele: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif Kimliği, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ### Billing issue converted grafiğinin kullanımı \{#billing-issue-converted-chart-usage\} Bu grafiği, ek süre dolduktan sonra fatura döngüsü içinde faturalandırma sorunlarının ne kadar etkili çözüme kavuşturulduğunu takip etmek için kullanın. Çözüm eğilimlerini zaman içinde izleyerek ödeme kurtarma süreçlerindeki kalıpları belirleyebilir ve faturalandırma sorunları sırasında ödeme yeniden deneme mantığınızda ya da iletişim stratejilerinizde yaptığınız değişikliklerin etkisini değerlendirebilirsiniz. ### Benzer metrikler \{#similar-metrics\} - [Faturalandırma sorunu](billing-issue) - [Faturalandırma sorunu çözüldü geliri](billing-issue-converted-revenue) - [İade tutarı](refund-money) - [İade olayları](refund-events) - [Ek süre](grace-period) - [Ek süre çözüldü](grace-period-converted) - [Ek süre çözüldü geliri](grace-period-converted-revenue) --- # File: billing-issue-converted-revenue --- --- title: "Faturalama sorunu dönüştürülmüş geliri" description: "Adapty'nin destek araçlarını kullanarak abonelik faturalama sorunlarını çözün." --- **Billing issue converted revenue** grafiği, [faturalama sorunu dönüşümlerinden](billing-issue-converted) elde edilen geliri gösterir: [Faturalama Sorunu](billing-issue) durumuna giren ve faturalama döngüsü sona ermeden yenilenen abonelikler. ### Hesaplama \{#calculation\} **Billing issue converted revenue** grafiği, mevcut faturalama döngüsünde [Fatura Sorunu](billing-issue) durumuna giren ve o gün yenilenen aboneliklerden elde edilen günlük geliri gösterir. Bir abonelik, mağaza (örneğin Apple, Google) aboneden çeşitli nedenlerle (süresi dolmuş kredi kartı veya yetersiz bakiye gibi) ödeme alamadığında Fatura Sorunu durumuna girer. Fatura Sorunu durumunda abonelik aktif sayılmaz; mağaza ayarlarında Ek Süre özelliği etkinleştirilmişse abonelik, yalnızca ek süre sona erdikten sonra Fatura Sorunu durumuna geçer. ### Mevcut filtreler \{#available-filters\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: - ✅ Filtreleme ölçütleri: Attribution, Kitle, İade Nedeni, Ülke, Teklif Türü, Teklif ID'si, Teklif İndirim Türü, Paywall, A/B testi, Placement, Dönem, Segment, Mağaza, Ürün ve Süre. - ✅ Gruplama ölçütleri: Ürün, Ülke, Mağaza, Paywall, Kitle, Placement, Süre, Segment ve Attribution. ### Fatura sorunu dönüşüm geliri grafiğinin kullanımı \{#billing-issue-converted-revenue-chart-usage\} Ek süre sona erdikten sonra aboneliklerden kurtarılan geliri izleyerek çözüme kavuşturulan fatura sorunlarının finansal etkisini ölçmek için bu grafiği kullanın. Bu sayede fatura sorunu kurtarma stratejinizin etkinliğini sayısal olarak değerlendirebilir ve faturalama yeniden deneme mekanizmaları ya da hedefli kullanıcı iletişimlerini hayata geçirmenin yatırım getirisini ölçebilirsiniz. ### Benzer metrikler \{#similar-metrics\} - [Fatura sorunu](billing-issue) - [Fatura sorunu dönüşümü](billing-issue-converted) - [İade tutarı](refund-money) - [İade olayları](refund-events) - [Ek süre](grace-period) - [Ek süre dönüşümü](grace-period-converted) - [Ek süre dönüşüm geliri](grace-period-converted-revenue) --- # File: ltv --- --- title: "Lifetime Value (LTV)" description: "Learn how to calculate and optimize Lifetime Value (LTV) in Adapty." --- Gerçekleşen LTV (Yaşam Boyu Değer) metriği, ödeme yapan müşteri kohortunun iade kesintilerinden sonra fiilen elde ettiği gelirin, o kohortdaki ödeme yapan müşteri sayısına bölünmesiyle hesaplanır. Dolayısıyla bu grafik, ödeme yapan her müşteriden ortalama olarak ne kadar gelir elde ettiğinizi gösterir. Adapty, LTV grafiğini uygulamanızın geliri ve müşteri davranışı hakkındaki birkaç önemli soruyu yanıtlayacak şekilde tasarlamıştır: 1. Her kohort, uygulamanızla geçirdiği süre boyunca ne kadar gelir getirir? 2. Bir kohort ne zaman kendini amorti eder? 3. Yüksek LTV'li, değerli müşteriler çekmek için uygulamanızın pazarlama ve kullanıcı edinme harcamalarını nasıl optimize edebilirsiniz? 4. Yeni müşteri edinme yatırımınızı geri kazanmanız ne kadar sürer? LTV grafiği, SDK'mız ve uygulama içi etkinlikler aracılığıyla topladığımız uygulama verileriyle çalışır. Bu bilgiler sayesinde aboneliklerinizin nasıl performans gösterdiğini ve belirli bir dönem içinde abonelerinizden ne kadar gelir elde ettiğinizi anlayabilirsiniz. Bu bilgileri abonelik teklifleriniz, reklam harcamalarınız ve müşteri edinme stratejileriniz hakkında bilinçli kararlar almak için kullanabilirsiniz. Ayrıca filtreler, verileri ülke, attribution ve diğer değişkenlere göre segmentlere ayırmanıza olanak tanıyarak müşteri tabanınızı daha ayrıntılı bir şekilde anlamanızı sağlar. ### Yenilemelere göre LTV \{#ltv-by-renewals\} **Yenilemelere göre LTV** görünümü, abonelik dönemiyle (P) ilgili verileri sunar ve özellikle bir müşterinin ödeme yaptığı ilk anı yakalar. Haftalık bir abonelikte bu, sonraki haftalık abonelik dönemine karşılık gelir. ### Günlere göre LTV \{#ltv-by-days\} **Günlere göre LTV** görünümü, verileri günlük, haftalık veya aylık aralıklara göre düzenler ve filtreler. Belirli bir gün, hafta veya ayda uygulamayı yükleyen tüm kullanıcıların ödeme yapan kullanıcı sayısına bölünerek elde edilen toplam gelire ilişkin öngörüler sunar. Bu görünüm, gelir takibi konusunda değerli bilgiler sağlar ve zaman içindeki kullanıcı davranışının kapsamlı biçimde anlaşılmasına olanak tanır. ### Kohort uzunluğu ve zaman aralığı \{#cohort-length-and-time-frame\} Tablonun ne göstereceğini iki zaman ayarı kontrol eder: - **Time frame** — tarih aralığı. Tablonun üzerindeki takvimden ayarlayın. - **Cohort length** — her satırın büyüklüğü: gün, hafta, ay, çeyrek veya yıl. Aylık uzunlukta her satır, bir aylık yüklemeyi kapsar. Bu ikisi birbirinden bağımsız çalışır. Örneğin: 6 aylık bir time frame ile aylık cohort length birleşince 6 satırlık bir tablo elde edersiniz. 1 yıllık time frame ile haftalık cohort length ise 52 satır verir. ### Hesaplama \{#calculation\} Gerçekleşen LTV, her müşteri kohortundan elde edilen toplam gelirden iadeler düşülerek hesaplanır. _Gün/hafta/aya ait LTV = O gün/hafta/ayda uygulamayı yükleyen tüm ödeme yapan kullanıcılardan elde edilen gelir / O gün/hafta/ayda uygulamayı yükleyen ödeme yapan kullanıcı sayısı_ LTV hesaplaması; yükseltme, düşürme ve yeniden aktivasyon durumlarını (örneğin kullanıcının abonelik planını veya fiyatlandırmasını değiştirmesi) kapsar. İlk abonelikten elde edilen geliri ve güncellenmiş plana dayalı sonraki yenilemeleri de hesaba katar. ### Mevcut gruplama ve filtreleme \{#available-grouping-and-filtering\} :::link Ana makale: [Analytics kontrolleri](controls-filters-grouping-compare-proceeds) ::: Filtreler ve gruplamalar, LTV grafiğinin hem yenilemeler hem de günler görünümlerine uygulanabilir; bu sayede belirli kohortlara derinlemesine inip zaman içindeki davranışlarını anlayabilirsiniz. - ✅ Şuna göre filtrele: Attribution, Kitle, Ülke, Paywall, A/B testi, Placement, Segment, Mağaza, Ürün ve Süre. - ✅ Şuna göre grupla: Ürün, Ülke, Mağaza, Süre, Segment ve Kohort (Gün, Hafta, Ay veya Yıl). Adapty'deki Realized LTV grafiği, müşteri davranışları hakkında değerli bilgiler edinmenize, pazarlama stratejilerini optimize etmenize, gelir performansını takip etmenize ve müşterilerinizin uzun vadeli değerini maksimize etmek için veriye dayalı kararlar almanıza yardımcı olur. --- # File: analytics-cohorts --- --- title: "Kohort analizi" description: "Kullanıcı etkileşimini ve abonelik trendlerini takip etmek için Adapty'deki analitik kohortları kullanın." --- Adapty kohortları birkaç önemli soruyu yanıtlamak için tasarlanmıştır: 1. Bir kohort kaçıncı günde kara geçiyor? 2. Uygulama belirli bir kohort için ne kadar para kazanıyor? 3. Ödeme yapan bir müşteriyi çekmek için ne kadar harcayabilirim? 4. Reklam harcamasını geri kazanmak ne kadar sürer? Kohortlar, SDK ve mağaza bildirimleri aracılığıyla topladığımız uygulama verileriyle çalışır; sizin tarafınızdan herhangi bir ek yapılandırma gerektirmez. ## Yenilemeler veya günler bazında kohortlar \{#cohorts-by-renewals-or-by-days\} Kohortları yenilemeler veya günler bazında analiz edebilirsiniz. Bu kontrol sütun başlıklarını değiştirir; dolayısıyla analiz yaklaşımı da değişir. **Günlere göre** takip, bütçeleme ve ödeme zamanlamalarını anlamak için değerli bilgiler sunar. Bu özellikle consumable veya tek seferlik satın alma gibi abonelik dışı ürünleri takip etmek için oldukça kullanışlıdır. Bu modda, tablo hücrelerindeki mavi renk iki temel faktör nedeniyle satırların ortasında yoğunlaşma eğilimindedir. Birincisi, kohortları günlere göre görüntülemek kısa süreli ürünlere ait ödemelerin erken görünür olmasını sağlarken, yenilemeler görünümünde bu ödemeler aylık ve yıllık yenilemelerle bir arada gruplanır. İkincisi, geciken ödemeler dağılım örüntüsüne katkıda bulunur; bazı kullanıcılar beklenenden geç ödeme yapar. **Yenilemeler bazında** izleme ise kohortların tarih gözetmeksizin bir ödemeden diğerine olan elde tutma ve kayıp oranlarını gösterir. Geç ödeyen kullanıcılar (aylarca gecikmiş olsalar bile) kendi abonelik dönemlerinin sayısına eklenir. Bu yaklaşım takvim bazlı kazançları yansıtmaz; ancak kohortların elde tutma ve kayıp oranlarını analiz etmek ve kullanıcı davranışından içgörüler elde etmek için çok daha kullanışlıdır. İstediğiniz modu seçin ya da daha fazla sonuç ve fikir için her ikisini birden kullanın. ## Adapty kohortları nasıl oluşturur \{#how-adapty-builds-cohorts\} Yenilemeler bazında kohortlar örneğiyle tablonun nasıl oluşturulduğuna bakalım. Kohort oluşturmak için iki ölçüt kullanırız: uygulama kurulumları ve işlemler (satın almalar). Bir kohortun her satırı belirli bir zaman aralığını temsil eder: bir günden bir yıla kadar. Her satır, bu aralıkta uygulamayı yükleyen ve bir abonelik etkinleştiren ya da süresiz/abonelik dışı ürün satın alan kullanıcı sayısıyla başlar. Satırdaki her sonraki sütun, aboneliğini bu döneme kadar yenileyen kullanıcı sayısını gösterir. M3 "3. ay" anlamına gelir ve abonelerin bu noktaya kadar 3 ardışık yenileme yaptığını ifade eder; W7 "7. hafta", Y2 ise "2. yıl" anlamına gelir. Kohortlarda bazen P2 de görebilirsiniz. P, abonelik dönemini (Period) ifade eder. Adapty, aynı kohortda farklı yenileme dönemlerine sahip birden fazla ürün bulunduğunda W/M/Y yerine bunu görüntüler. Kohort değerlerindeki farklılıkları vurgulamak için degrade renkler kullanırız. En yüksek sayılar daha doygun renklere sahiptir. Aşağıdaki görselde tipik bir kohort görebilirsiniz. 1. Bu kohort yalnızca haftalık ürünlere ait verileri göstermektedir (işaret #1). 2. Geliri kesintisiz göstermekte ve mutlak değerler olarak sunmaktadır (işaret #2). 3. Çalıştığımız zaman aralığı son 6 ay, kohort uzunluğu ise 1 aydır (işaret #3). 4. **Total** satırı (işaret #4), her dönem için kümülatif değeri gösterir. **Total** satırının ilk hücresindeki 442 bin dolar, zaman aralığının sonuna kadar tüm aylara (Kas, Ara vb.) ait ilk dönem (abonelik aktivasyonu) gelirini birikimli olarak toplar. Total hücresi, tüm dönem boyunca uygulamayı yükleyen müşteri sayısını gösterir. 5. Kas 2023 satırının ilk sütunu (işaret #5), Kas 2023'te uygulamayı yükleyen müşterilere ait ilk dönem (abonelik aktivasyonu) geliri olan 37,7 bin doları gösterir. Kas 2023'te uygulamayı yükleyen müşteri sayısı olan 95.129, başlık sütununda gösterilmektedir. Kas 2023 satırının ikinci sütunu, Kas 2023'te uygulamayı yükleyen kullanıcılara ait 2. hafta (aboneliklerin 2. haftaya yenilenmesi) geliri olan 8,77 bin doları gösterir. 6. Tabloda Toplam gelir, ARPU, ARPPU ve ARPAS değerlerini görebilirsiniz (işaret #6). Bunlar hakkında daha fazla bilgiyi bu makalenin ilerleyen bölümlerinde bulabilirsiniz. 7. Sütunları, tablonun sağ tarafındaki **Columns** açılır alanını kullanarak yapılandırabilirsiniz (işaret #7). 8. Tablonun sağ üst kısmında (işaret #8), belirli kohort analizleri için mağaza komisyon ücretlerini ve vergi hesaplamalarını yapmaya yarayan bir açılır alan da bulunmaktadır. Adapty'nin mağaza komisyon ücretlerini ve vergileri nasıl hesapladığını [bu makalede](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) öğrenebilirsiniz. Açılır listeden ilgili seçeneği seçtiğinizde gelir verileri buna göre yeniden hesaplanır. 9. Tablonun sağ tarafında tahmini gelir (Predicted Revenue) ve tahmini yaşam boyu değeri (Predicted LTV) görebilirsiniz (işaret #9). **Predicted Revenue** alanı, bir abone kohortunun belirli bir zaman diliminde elde etmesi beklenen toplam geliri tahmin ederken, **Predicted LTV** alanı kohortdaki her kullanıcının beklenen değerini temsil eder. Belirli bir döneme ait ayrıntılı metrikleri görüntülemek için kohort tablosundaki herhangi bir hücrenin üzerine gelebilirsiniz. Arka planında çapraz çizgiler bulunan hücreler henüz tamamlanmamış dönemleri temsil eder; bu nedenle içerdikleri değerler artmaya devam edebilir. ## Kohort uzunluğu ve zaman dilimi \{#cohort-length-and-time-frame\} Tablonun ne göstereceğini iki zaman ayarı kontrol eder: - **Time frame** — tarih aralığı. Tablonun üzerindeki takvimden ayarlayın. - **Cohort length** — her satırın büyüklüğü: gün, hafta, ay, çeyrek veya yıl. Aylık uzunlukta her satır, bir aylık yüklemeyi kapsar. Bu ikisi birbirinden bağımsız çalışır. Örneğin: 6 aylık bir time frame ile aylık cohort length birleşince 6 satırlık bir tablo elde edersiniz. 1 yıllık time frame ile haftalık cohort length ise 52 satır verir. ## Filtreler, metrikler, kohort segmentleri ve CSV olarak dışa aktarma \{#filters-metrics-cohort-segments-and-export-in-csv\} :::link Ana makale: [Analitik kontrolleri](controls-filters-grouping-compare-proceeds) ::: Adapty, varsayılan olarak tüm satın almaların verilerini kullanarak kohortlar oluşturur. Ürün süresi, belirli ürünler, ülke, mağaza, paywall, segment ve attribution verisine göre filtreleme yapabilirsiniz. Kontrol panelinin sağ tarafında kohort verilerini CSV olarak dışa aktarma düğmesi bulunur. Dışa aktardığınız dosyayı Excel veya Google Sheets'te açabilir ya da kendi analitik sisteminize aktarabilirsiniz. Kohortlarda gösterilebilecek 6 metrik vardır: Subscriptions, Payers, Revenue, ARPU, ARPPU ve ARPAS. Bunları mutlak değerler olarak ya da kohortun başlangıcından itibaren göreli değişim olarak görüntüleyebilirsiniz. ## Abonelikler, ödeyenler, toplam gelir, ARPU, ARPPU ve ARPAS \{#subscriptions-payers-total-revenue-arpu-arppu-and-arpas\} **Abonelikler**, bir kohortun seçilen zaman dilimi içinde gerçekleştirdiği aktif abonelikler, süresiz erişim satın almaları ve tek seferlik satın almaların toplam sayısıdır. Bu metriği takip etmek, müşteri davranışını ve tekliflerinizin etkinliğini anlamanıza yardımcı olur. Bu içgörü sayesinde ürün stratejinizi geliştirebilir, pazarlama çalışmalarınızı özelleştirebilir ve gelir akışlarınızı optimize edebilirsiniz. **Ödeme yapanlar**, bir kohort içinde satın alma yapan toplam benzersiz kullanıcı sayısıdır. Kaç benzersiz kullanıcının gelirinize katkıda bulunduğunu anlamanıza yardımcı olur. Önemli miktarda abonelik dışı satın alma içeren uygulamalar için bu metrik, ürün tekliflerinizin gerçek erişimini vurgulayabilir; geniş bir kullanıcı tabanının satın alma yapıp yapmadığını veya gelirin tekrar satın alan küçük bir grup tarafından mı sağlandığını gösterir. Ödeme yapan kullanıcı sayısını anlamak, müşteri etkileşimini değerlendirmede, hedefli pazarlama planlamada ve gelir stratejilerini optimize etmede yardımcı olur. **Toplam gelir**, seçilen zaman diliminde (25 Kas 2022 — 24 May 2023) bir kohort için birikimlenen gelirdir. Belirli bir kohorttaki kullanıcılardan ne kadar para topladığınızı anlamanıza ve ROAS hesaplamanıza yardımcı olur. Örneğin Eylül 2022 reklam harcaması 10.000 dolar ve Eylül 2022 kohortu için toplam gelir 30.000 dolarsa ROAS=3:1 olur. **ARPU**, kullanıcı başına ortalama gelirdir. Toplam gelir / benzersiz kullanıcı sayısı olarak hesaplanır. 60.000 dolar gelir / 5.000 kullanıcı = 12 dolar ARPU. Bu değeri kurulum maliyetiyle (CPI) karşılaştırmak, pazarlama kampanyalarınızın etkinliğini anlamak açısından faydalıdır. **ARPPU**, ödeme yapan kullanıcı başına ortalama gelirdir. Toplam gelir / benzersiz ödeme yapan kullanıcı sayısı olarak hesaplanır. 60.000 dolar gelir / 1.000 ödeme yapan kullanıcı = 60 dolar ARPPU. Ortalama olarak ödeme yapan bir müşterinin size ne kadar para kazandırdığını anlamanıza yardımcı olur. **ARPAS**, aktif abone başına ortalama gelirdir. Toplam gelir / aktif abone sayısı olarak hesaplanır. Abone olarak, deneme süresi veya abonelik etkinleştirenleri kastediyoruz. 60.000 dolar gelir / 1.500 abone = 40 dolar ARPAS. ## Komisyon ücretleri ve vergiler \{#commission-fees-and-taxes\} Kohort analitiğinde gelir hesaplamasının önemli bir yönü, mağaza komisyon ücretleri ve vergilerin dahil edilmesidir (bunlar, kullanıcının mağaza hesabının bulunduğu ülkeye göre farklılık gösterebilir). Adapty, kohort analitiğinde hem App Store hem de Play Store için komisyon ücreti ve vergi hesaplamayı desteklemektedir. Adapty'nin analitiğinde vergi ve komisyonları nasıl hesapladığına dair ayrıntılar için [belgelere](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) göz atabilirsiniz. ## Gelir ve Hasılat \{#revenue-vs-proceeds\} Gelir ve Hasılat, ikisi de para metrikleridir. Geliri brüt gelir, Hasılatı ise net gelir olarak düşünebilirsiniz. Gelir, App Store / Play Store komisyonlarını hesaba katmazken Hasılat bu komisyonları düşer. Bu nedenle Hasılat her zaman Gelir'den azdır. Kesilen komisyon oranı; [Küçük İşletme Programı](app-store-small-business-program) (%15) gibi programlara uygunluk, uzun vadeli aboneliklerde indirimli oranlar (bir yıllık yenilemeden sonra %15), ülkeye özgü oranlar ve standart oranlar (%30'a kadar) gibi birden fazla faktöre bağlı olarak değişir. Adapty, müşterilerinizin gerçekleştirdiği her işlem için geçerli komisyon oranını otomatik olarak belirler ve buna göre Geliri hesaplar. Komisyon oranlarının nasıl belirlendiği hakkında daha fazla bilgi için [Mağaza komisyonu ve vergiler](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) belgelerine bakın. ## İade işleme \{#refund-handling\} İki kural her kohort metriği için geçerlidir: - Bir iade, orijinal satın alma tarihine değil, yapıldığı güne göre tarihlenir. Bir iade, yalnızca iade tarihi seçilen zaman dilimine girdiğinde bir kohortu etkiler. - Bir iade, kullanıcıyı kohortundan hiçbir zaman çıkarmaz ve yükleme sayısını asla değiştirmez. Kohort üyeliği, kullanıcı uygulamayı yüklediğinde belirlenir. Bu kurallara ek olarak, bir iadenin etkisi metriğe ve [görünüm moduna](#cohorts-by-renewals-or-by-days) bağlıdır. Kullandığınız mod için sütunu aşağıya doğru okuyun. | Metrik | Yenilemelere göre | Günlere göre | | --- | --- | --- | | Yüklemeler (kohort boyutu) | Etkilenmez. Kullanıcı kendi kohortunda kalır. | "Yenilemelere göre" ile aynı. | | Abonelikler | İade edilen abonelikler yine de sayılır. | İade, aboneliği sayımdan çıkarır. | | Ödeyenler | İade edilen ödeme yapan kullanıcılar yine de sayılır. | İade, kullanıcıyı sayımdan çıkarır; başka başarılı ödemeleri olsa bile. | | Gelir | İade edilen tutar, ödemenin başlangıçta sayıldığı yenileme dönemi sütunundan düşülür. | İade edilen tutar, iade gününden itibaren düşülür. | | ARPU | Gelir / yükleme sayısı. İade geliri düşürür; yükleme sayısı hiçbir zaman değişmez. | "Yenilemelere göre" ile aynı. | | ARPPU | Gelir / ödeme yapan kullanıcı sayısı. İade hem geliri hem de ödeme yapan kullanıcı sayısını düşürebilir; bu nedenle ARPPU, yalnızca gelire kıyasla daha sert hareket edebilir. | "Yenilemelere göre" ile aynı. | | ARPAS | Gelir / aktif abone sayısı. İade geliri düşürür; abone sayısı değişmez. | "Yenilemelere göre" ile aynı. | | Elde tutma | Etkilenmez. Deneme ve satın alma olaylarını sayar, iadeleri saymaz. | "Yenilemelere göre" ile aynı. | İade, aktif gelir muhasebe modundan bağımsız olarak iade edilen tutarı gelirden düşer. ### Dönüşüm oranı ve ARPPU \{#conversion-rate-and-arppu\} Geri ödemeler, yükleme sayısı değişmediğinden yükleme bazlı dönüşüm oranını etkilemez. Ödeme yapan kullanıcı bazlı dönüşüm oranı ise farklıdır. Geri ödemeler, **by days** görünümünde bu oranı düşürür; ancak **by renewals** görünümünde düşürmez. **Yenilemeler bazında** görünümde, Gelir ve Ödeme Yapanlar sütunlarının her biri yalnızca tek bir dönemi gösterir. ARPPU sütunu ise bunu yapmaz. Her ARPPU hücresi, kohortun ilk döneminden sütunun dönemine kadar olan her şeyi toplar. Dolayısıyla her zaman birden fazla dönemi kapsar ve iade alan kullanıcıları dışarıda bırakır. Bu nedenle, tek bir dönemin Gelirini o dönemin ödeme yapan kullanıcılarına bölerek gösterilen ARPPU değerine ulaşamazsınız. **Örnek.** Bir kullanıcı Şubat'ta uygulamayı yükler ve bir abonelik satın alır, ardından Nisan'da tam iade alır. Şubat kohortunu **günler bazında** görüntülerken: - Zaman dilimi Şubat–Mart, geri ödeme pencereye girmeden önce: kullanıcı 1 ödeyen kullanıcı olarak sayılır ve geliri tam olarak dahil edilir. - Zaman dilimi Şubat–Haziran, geri ödeme pencereye girdikten sonra: kullanıcı 0 ödeyen kullanıcı olarak sayılır ve geliri 0'a düşer. Her iki zaman diliminde de Şubat yükleme sayısı ve Retention aynı kalır. [Metriklerin geri ödemeleri nasıl ele aldığı](refund-events#how-metrics-handle-refunds), MRR, gelir grafikleri ve veri dışa aktarmalarındaki aynı kuralları karşılaştırır. ## Tahmin: Gelir ve LTV \{#prediction-revenue-and-ltv\} **Tahmini gelir**, ödeme yapan abonelerden oluşan bir kohortun, kohort oluşturulduktan itibaren seçilen süre içinde üretmesi beklenen toplam tahmini gelirdir. Kohortun tahmini LTV'si ile kohorttaki tahmini ödeme yapan kullanıcı sayısının çarpımıyla hesaplanır. Örneğin tahmini LTV 50 $ ve bir kohortta 100 ödeme yapan kullanıcı varsa Tahmini Gelir 5.000 $ olur. **Tahmini LTV**, ödeme yapan abone başına düşen tahmini yaşam boyu değerdir; kohort oluşturulduktan sonra seçilen dönem içinde her ödeme yapan abonenin ortalama olarak ne kadar gelir üreteceğini gösterir. Bu tahminler, geçmiş kohort elde tutma kalıplarına dayanır; yeterli geçmiş verisi mevcut olduğunda uygulamanın kendi verileri, aksi takdirde uygulamalar arası ortalamalar kullanılır. Adapty'nin tahmin modeline ilişkin ayrıntılı belgeler için [Tahmin belgelerimize](predicted-ltv-and-revenue) bakabilirsiniz. Adapty kohortları, uygulamanızdaki kullanıcı davranışı ve finansal performans hakkında ayrıntılı içgörüler sunar. Kohortları yenilemeler veya günler bazında analiz ederek kohortların ne zaman kârlı hale geldiğini belirleyebilir, geliri takip edebilir, kullanıcı başına ortalama geliri hesaplayabilir ve reklam harcamalarını geri kazanma süresini anlayabilirsiniz. Özelleştirilebilir filtreler, metrikler ve dışa aktarma seçenekleriyle Adapty, veri odaklı kararlar almanızı ve maksimum uygulama başarısı için kullanıcı edinme ile para kazanma stratejilerinizi optimize etmenizi sağlar. --- # File: analytics-funnels --- --- title: "Huni analizi" description: "Dönüşümleri artırmak ve kullanıcı davranışını izlemek için Adapty'deki analitik hunilerini anlayın." --- Adapty hunileri şu tür soruları yanıtlamanıza yardımcı olmak için tasarlanmıştır: 1. Yüklemelerin yüzde kaçı ödeme yapan müşteriye dönüşüyor? 2. Ürünü deneyenlerin ne kadarı sadık kullanıcıya dönüşüyor? 3. Hangi adımlarda yüksek oranda düşüş yaşanıyor ve daha fazla ilgi gerektiriyor? 4. Müşteriler neden ödeme yapmayı bırakıyor? Huni grafiği ile filtreler ve gruplar ayarlayarak kullanıcı davranışı hakkında daha fazla içgörü elde edebilirsiniz. Huniler, SDK ve mağaza bildirimleri aracılığıyla topladığımız verilerle çalışır ve sizin tarafınızdan herhangi bir ek yapılandırma gerektirmez. :::note Huniler, kurulum verilerini [App Settings](general#4-installs-definition-for-analytics) içindeki kurulum tanımınıza göre yansıtır. ::: <img src="/assets/shared/img/funnels-tab.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Huni grafiğini adım adım inceleyelim \{#funnel-chart-step-by-step\} Kullanıcı yolculuğunu grafik üzerinde nasıl okuyacağınızı anlamak için huninin öğelerini birlikte inceleyelim. ### Kurulumlar \{#installs\} 1. sütun (1), kurulum sayısını gösterir. Bu değer; toplam kurulum sayısının (benzersiz kullanıcı sayısı değil) mutlak değeri (2) olarak ve sonraki dönüşümlerin göreli hesaplamasında temel alınan en büyük giriş sayısı olarak %100 şeklinde gösterilir. Bir kullanıcı uygulamayı silip yeniden yüklerse iki ayrı kurulum sayılır. Yanındaki gri alan, adımlar arasındaki geçiş parametrelerini temsil eder. Sonraki adıma (Görüntülenen paywall) geçiş yüzdesi bir bayrak üzerinde (3) gösterilir. Düşüş yüzdesi ve kaybın mutlak değeri ise alt kısımda (4) yer alır. <img src="/assets/shared/img/00416f9-CleanShot_2022-06-23_at_14.02.06.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Paywall görüntülendi \{#paywall-displayed\} 2. sütun (5), uygulamanın en az bir kez paywall gören kullanıcı sayısını (6) gösterir. Bu sayıya yalnızca seçili dönemde gerçekleşen kurulumlar dahil edilir. Bir kullanıcı, seçili dönemde paywall görse bile kurulum tarihi aralık dışındaysa bu görüntüleme sayılmaz. Ayrıca bu görüntülemelerin 1. adıma göre yüzdesi de gösterilir (7). Bu yüzdenin, 1. adımdaki gri bayrakla (3) eşit olduğunu fark edebilirsiniz. Bu eşitlik yalnızca bu ilk adımlar için geçerlidir. Bu adım için tüm veriler, `logShowFlow()` (iOS SDK v4+) / `logShowPaywall()` metodunu kullanan paywalllarınızdan toplanır. Bu nedenle, her paywall görüntülemeyi [dokümanlarda](present-remote-config-paywalls#track-paywall-view-events) açıklandığı gibi bu metodu kullanarak Adapty'ye gönderdiğinizden emin olun. 2. sütunun yanındaki gri alan geçişi temsil eder. Bir sonraki adıma (Trial) dönüşüm yüzdesi bayrak üzerinde gösterilir (8). Paywall sonrasında kaybedilen müşterilerin düşüş yüzdesi ve mutlak değeri aşağıda gösterilir (9). <img src="/assets/shared/img/fb11650-CleanShot_2022-06-23_at_15.54.32.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Denemeler \{#trials\} 3. sütun (10), seçilen dönemde (11) uygulamayı yükleyen müşterilerin paywalllar üzerinden etkinleştirdiği deneme sayısını gösterir. Filtre deneme içermeyen ürün(ler)e ayarlandığında bu değer sıfır olur ve sütun boş görünür. 1. adımdan denemeye alınan kullanıcı yüzdesini de görebilirsiniz; bu, yüklemelerden denemele dönüşümü temsil eder (12). Bu yüzdenin, bir önceki adım dönüşümünün gri bayrağıyla (8) aynı olmadığını fark edebilirsiniz. Bunun nedeni, mevcut değeri hem grafiğin en üstündeki 1. adımla hem de gri bayraklardaki bir önceki adımla karşılaştırmamızdır. Dolayısıyla 3. sütunun yanındaki gri alan, bayrakta (13) gösterilen bir sonraki adıma (Ücretli) dönüşüm yüzdesini gösterir. Deneme süresi boyunca kaybedilen müşterilerin düşüş yüzdesi ve mutlak değeri ise aşağıda gösterilmektedir (14). <img src="/assets/shared/img/7b88909-CleanShot_2022-06-23_at_15.54.32_-_2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Abonelikler ve yenilemeler \{#subscriptions-and-renewals\} 4. sütun, etkinleştirilen abonelik sayısını (15) gösterir. Deneme süresi olmayan ürünler için bu sayı, paywall üzerinden yapılan doğrudan abonelikleri içerir. Deneme süresi olan ürünler için ise ücretli aboneliğe dönüştürülen deneme sayısını kapsar. Her iki türde ürününüz varsa (deneme süreli ve deneme süresiz), bu değer ikisinin toplamı olur. Üstteki yüzde, yüklemelerden dönüşümü gösterir (16). Gri bayraktaki yüzde, bir sonraki adıma geçişi (2. döneme yenileme) gösterir (17). 2. döneme yenilemeden önceki düşüş yüzdesi ve mutlak değeri, dönüşümün altında gösterilir (18). <img src="/assets/shared/img/d13bf9b-CleanShot_2022-06-23_at_15.54.32-3.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adım, benzer yapıya sahip bir dizi adımı başlatır. 2. yenilemeden sonra 3., ardından 4. gelir ve bu böyle devam eder. Uygulama geçmişinizde yeterince veri varsa, yatay kaydırma ile düzinelerce dönem görebilirsiniz. Bu adımların mantığı aynı kalır: - en üstte kurulumlardan yüzde, - en altta önceki adımdan yüzde, - en üstte mutlak yenileme miktarı, - en altta mutlak churn miktarı, - churn nedenleri açılır penceresi için üzerine gelme. ### Churn nedenleri \{#churn-reasons\} Adapty, Trial aşaması ve sonrası için *churn* istatistiklerini ayrıntılı olarak gösterir. Bir aşamaya girip bir sonrakine geçemeyen her kullanıcı, bir churn örneği olarak sayılır. * Belirli bir olay (örneğin, trial süresinin dolması veya ödeme sorunu) dönüşüm eksikliğine neden olduysa, Adapty bu nedeni görüntüler. * **unknown** durumu geçici bir durumdur. Kullanıcının henüz bir sonraki aşamaya geçmesini sağlayacak olayla karşılaşmadığını gösterir. Deneme aşamasında bu durum genellikle deneme süresinin henüz sona ermediği anlamına gelir. Bu, kısa tarih aralıkları veya tek günlük Funnel görünümlerinde sıkça yaşanır; zira denemelerin sonuçlanması zaman alır. Kullanıcı denemeyi satın alım olarak tamamladığında veya iptal ettiğinde Adapty bilgileri günceller. <img src="/assets/shared/img/churn-reasons.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Tablo görünümü, filtreler ve CSV dışa aktarımı \{#table-view-filters-and-csv-export\} Huni grafiği, sayılarla çalışırken işe yarayacak kullanışlı materyaller sunmak amacıyla tablo biçimindeki verilerle zenginleştirilmiştir. <img src="/assets/shared/img/4787aff-CleanShot_2022-06-23_at_21.01.44.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu tablo, dönüşüm hunisiyle aynı yaklaşımı bazı değişikliklerle tekrar eder. 1. ücretli abonelik adımı dışındaki tüm adımlara ait verileri gösteren sütunlar bulunur. Bu adım yerine iki ayrı sütun yer alır: Install -> Paid ve Trial -> Paid. Bunlar, ücretsiz bir kullanıcının ödeme yapan birine dönüştüğü temel dönüşüm noktasını gösterir. Install → Ödeme sütununun yalnızca deneme süresi olmayan ürünleri, Trial → Ödeme sütununun ise yalnızca deneme süresi olan ürünleri gösterdiği gibi bir ürün türü ayrımı varmış gibi görünebilir. Ancak iş tam olarak böyle işlemiyor. Çünkü deneme süresi dolmuş ve ardından deneme süresi olan bir ürünü sanki yokmuş gibi satın alan kullanıcıları da bu hesaba dahil ediyoruz. <img src="/assets/shared/img/a9bcbc7-CleanShot_2022-06-23_at_21.29.12.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Sayılara daha derine inerek, yeni hipotezler için güçlü filtreleme araçları bulacaksınız. Farklı boyutlarda koşullar belirlemekten çekinmeyin. Veriye dayalı gerçek içgörüler elde edin. Değiştirin: 1. Ürün türü - ekonomi, süre vb. 2. Zaman aralığı. 3. Ülke segmentasyonu. 4. Traffic attribution. 5. Mağaza. Yalnızca gerekli verileri görüntülemek için Mutlak Sayı, Göreli % veya her ikisini seçin. <img src="/assets/shared/img/1475e42-CleanShot_2022-06-23_at_21.50.33_-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Son olarak, kontrol panelinin sağında huni verilerini CSV olarak dışa aktarma düğmesi bulunur. Bunu Excel'de, Google Sheets'te açabilir ya da kendi analitik sisteminize aktarabilirsiniz. :::important Uygulamanız indirimli komisyon programına kayıtlıysa Adapty'ye bildirin. Doğru hesaplamalar için [Küçük İşletme Programı](app-store-small-business-program) ve [İndirimli Hizmet Ücreti programı](google-reduced-service-fee) durumunuzu [uygulama ayarlarınızda](general) belirtin. ::: <img src="/assets/shared/img/ff23846-CleanShot_2022-06-23_at_22.15.49.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: analytics-retention --- --- title: "Elde tutma analizi" description: "Kullanıcı elde tutma analizini anlayın ve abonelik stratejinizi optimize edin." --- Elde tutma grafikleri şu sorulara yanıt bulmanıza yardımcı olabilir: 1. Uygulamanız kullanıcıları dönemden döneme nasıl elde tutuyor? 2. Hangi ürünler daha çekici ve daha iyi tutuyor? 3. Hangi kullanıcı grupları daha sadık? 4. Büyüme için kıyas noktası olarak hangi retention seviyesi kullanılabilir? 5. Ve tabii ki, yeni kullanıcı edinmek yerine mevcut kitleye yatırım yaparak nasıl para tasarrufu yapabilirsiniz. Filtreler ve gruplar ayarlayarak kullanıcı davranışı hakkında değerli içgörüler elde edeceksiniz. Retention, SDK ve mağaza bildirimleri aracılığıyla topladığımız verilerle gerçekleştirilir; sizin tarafınızdan herhangi bir ek yapılandırma gerektirmez. ### Elde tutmayı nasıl hesaplıyoruz? \{#how-do-we-calculate-retention\} Elde tutma grafiğini incelerken, kullanıcı sayısının hangi adımda olduklarına göre nasıl değiştiğini görebilirsiniz: deneme (eğer "deneme sürümlerini göster" onay kutusu işaretliyse), 1. ödeme, 2. ödeme vb. Elde tutma grafiği için bir tarih aralığı seçtiğinizde hangi kullanıcıların sayıldığını açıklayalım. Örneğin, takvimde son 3 ayı seçtiniz ve "deneme sürümlerini göster" onay kutusu işaretli değil. Bu durumda yalnızca son 3 ay içinde ilk aboneliğini başlatanlar sayılır. Eğer "deneme sürümlerini göster" onay kutusu işaretliyse ve takvimde son 3 ay seçiliyse, son 3 ay içinde deneme sürümü başlatmış olan herkes sayılır. Bu aboneler için, N. adımdaki mutlak elde tutma değeri, N. ödemeyi gerçekleştirenlerin sayısı olarak gösterilir. N. adım için göreli elde tutma değeri ise N. ödemenin mutlak miktarının, seçilen zaman aralığındaki toplam abonelik (veya deneme sürümü) sayısına oranı olarak hesaplanır. :::info Retention geriye dönük olarak değişir Grafiği ne zaman kontrol ettiğinizden bağımsız olarak, seçilen zaman dilimi için baz sayı (%100) sabit kalır. Öte yandan bir sonraki döneme ait retention değeri zamanla artabilir. Örneğin, aylık bir abonelikte 1-31 Aralık tarihleri arasında 20 ilk satın alma gerçekleştiyse, kullanıcılar çeşitli nedenlerle (ör. ek süre) bir sonraki abonelik dönemine zamanında ya da daha geç girdikçe ikinci döneme ait retention değerinin Ocak ayı boyunca (ve hatta sonrasında bile) artmaya devam etmesi beklenir. ::: ### İade işleme \{#refund-handling\} İadeler, elde tutma hesaplamalarından **çıkarılmaz**. İade yapan bir kullanıcı, elde tutma eğrisinde sayılmaya devam eder; bu da Retention'ı aynı kohort için [Aktif abonelikler](active-subscriptions) veya [Gelir](revenue)'den daha yüksek gösterebilir. Metrikler genelinde tam karşılaştırma için bkz. [Metriklerin iadeleri nasıl işlediği](refund-events#how-metrics-handle-refunds). ### Elde tutma fırsatları \{#retention-opportunities\} Adapty'nin elde tutma özelliğinden nasıl daha fazla yararlanabileceğimize bakalım. Yalnızca sayılara olan tutkuyla yetinmek yerine, analitik sonuçların uygulamaya konulmasından gerçek iş değeri çıkarmak istiyorsak önce amaçları düşünmek gerekir. Grafik özelliklerini derinlemesine incelediğimizde, bu verinin ne gibi bir etki yaratabileceğini anlamlandırmak faydalı olacaktır. O hâlde NİÇİN ve NASIL sorularını birlikte ele alalım. 1 - Hedef kitleyle çalışın. Her şeyden önce, elde tutma (retention); hedef kitle, bu kitlenin tercihleri ve ürününüzün tüketim süreci boyunca onların beklentilerini karşılayıp karşılamadığıyla doğrudan ilgilidir. İşletmenizin para kazandıran temel ilişkisini nasıl ölçeceğinizi merak ettiyseniz, retention tam da aradığınız şeydir. Bu ölçüm değerlidir; çünkü mevcut müşterinize satış yapmak, yeni birine satış yapmaktan genellikle çok daha ucuzdur. Bu maliyetin düşük olmasının iki nedeni vardır: satış için daha az çaba gerekmesi ve daha yüksek ortalama sepet tutarı. Dolayısıyla retention düştüğünde abonelerinizin bağlılığına yatırım yapmak akıllıca bir tercih olabilir. 2 - Ürünle çalışın. İKİNCİ neden şu: elde tutma grafikleri, ürününüzün gerçek kullanım ömrünü gösterir ve uzun vadeli tahmin yapmanıza olanak tanır. Geliştirmek istiyorsanız, ürünü kullanıcıya ulaştıran süreci düzeltin, ömrünü değiştirin ve ardından iş hedeflerinize daha yakın sonuçlar elde etmek için yeniden tahmin yapın. Bu tür güncellemeler, bir tahmin rutiniyle birlikte işleyen stratejik bir vizyonun parçası olabilir. Ve evet, bu süreç hiç bitmez; çünkü hepimiz, sürekli değişen bir ortamda aynı yerde kalabilmek için hızla koşuyoruz. 3 - pazar ile çalışmak. Ana rakiplerden daha hızlı hareket etmek iyidir, ancak bazen sıradan yarışın dışına çıkmak daha fazla fayda sağlayabilir. Farklı ülkelerdeki ve mağazalardaki kullanıcı davranışlarını analiz ettiğinizde, bazı yerel özellikler olağanüstü içgörüler ve iş için yeni fırsatlar ortaya çıkarabilir. Kültürel ve pazar bağlamı, daha sonra segmentasyon ve gelecekteki gelişim için kullanılmak üzere elde tutma perspektifinden analiz edilebilir. Örneğin, bazı bölgelerde mavi okyanus bulabilir ve orada daha hızlı büyüyebilirsiniz. Retention verilerinin kullanımı elbette bu temel yorumla sınırlı değildir; ancak hızlıca gerçek değer elde etmek istiyorsanız iyi bir başlangıç noktası olabilir. ### Eğriler, tablo görünümü, filtreler ve CSV dışa aktarma \{#curves-table-view-filters-and-csv-export\} Artık elde tutma amacını ve temel yorumlama yöntemlerini anladığımıza göre, her şeyi kullanışlı hale getiren araçları inceleyelim. Adapty'deki elde tutma özelliğinin özü grafiktir. Grafik, elde tutma düzeyinin bir müşterinin yaşam süresinin adımlarına göre nasıl değiştiğini gösterir. Adımlar yatay eksende gösterilir: Trial, Paid (1. abonelik), P2 (2. abonelik), P3, P4, vb. "Show trials" onay kutusu seçili olduğunda eksen yalnızca Trial adımıyla başlar. Veri hesaplama açısından bu onay kutusu şu şekilde çalışır: "Show trials" seçili olduğunda ve eksen Trial adımıyla başladığında, yalnızca trial içeren senaryolar görüntülenir; kurulumdan doğrudan gelen işlemler gösterilmez ve Paid adımı yalnızca trial'lardan gelen işlemleri içerir. "Show trials" seçili olmadığında ve eksen Paid adımıyla başladığında, bu ilk adım hem trial'lardan hem de doğrudan kurulumlardan gelen ilk işlemlerin tamamını içerir. Grafiğin üzerine geldiğinizde, veri özeti içeren bir açılır pencere görüntülenir. Aşağıdaki tablodaki bir sütunun üzerine geldiğinizde de grafikte ilgili verileri içeren bir özet açılır penceresi görürsünüz. Tablo, grafik için seçilen gruplandırma ve filtrelerin aynısını içerir. Gelişmiş analiz için filtreleri ve gruplamayı özgürce birleştirin. Veriye dayalı gerçek içgörüler elde edin. Şunlara göre değiştirebilirsiniz: 1. Ürün türü. 2. Süre. 3. Zaman aralığı. 4. Ülke. 5. Traffic attribution. 6. Mağaza. Gerekli verileri görüntülemek için #Mutlak ve %Göreli kontrolünü kullanın. Son olarak, kontrol panelinin sağında huni verilerini CSV olarak dışa aktarma butonu bulunur. Ardından bunu Excel'de veya Google Sheets'te açabilir ya da kendi analitik sisteminize aktararak analiz ve tahminlerinizi tercih ettiğiniz ortamda sürdürebilirsiniz. :::warning Uygulamanızın Küçük İşletme Programı'na dahil olduğunu [Adapty Genel Ayarları](https://app.adapty.io/settings/general)'nda belirttiğinizden emin olun. ::: --- # File: analytics-conversion --- --- title: "Dönüşüm analizi" description: "Adapty'nin analiz araçlarını kullanarak abonelik dönüşüm oranlarını ölçün." --- Huniler size üst düzey bir genel bakış sunarken, retention kullanıcı sadakatine odaklanır; dönüşüm analizi ise kullanıcı yolculuğundaki her kritik adımın etkinliğini zaman içinde değerlendirmenize yardımcı olmak için tasarlanmıştır. Dönüşümler şu soruları yanıtlamanıza yardımcı olur: 1. Uygulama dönüşümleri zaman içinde nasıl değişiyor? Mevsimsel trendler var mı? 2. Pazarlama faaliyetleri veya yeni koşullar sırasında dönüşümler nasıl değişiyor? 3. Farklı bölgelerdeki kullanıcılar uygulama güncellemelerinize nasıl tepki veriyor? 4. Hangi ürün türleri zaman içinde daha iyi dönüşüm sağlıyor? Dönüşüm, Adapty SDK ve mağaza bildirimleri aracılığıyla topladığımız verilerle hesaplanır; sizin tarafınızdan herhangi bir ek yapılandırma gerektirmez. ## Ana kontroller ve grafikler \{#main-controls-and-charts\} Gelir, başarıyı ölçmek için sıkça başvurulan bir metrik olsa da büyük resmin yalnızca bir parçasıdır. İşinizin zaman içinde nasıl performans gösterdiğini — farklı kullanıcı davranışları ve yaşam döngüsü aşamaları genelinde — anlamak da en az gelir kadar önemlidir. İşte tam burada dönüşüm analitiği devreye girer. Filtreler ve gruplar ayarlayarak kullanıcı davranışı hakkında daha değerli içgörüler elde edebilirsiniz. Trendleri belirlemek ve analiz etmek için dönüşümlerinizin günlük, aylık veya yıllık bazda nasıl değiştiğini takip edin. Grafiğin sol tarafında dönüşüm adımları kontrolünü bulacaksınız. Bu kontrol, hangi dönüşümleri takip edeceğinizi seçmenizi sağlar; örneğin Yükleme → Deneme, Deneme → Ücretli veya Ücretli → Yenileme gibi. Her dönüşüm metriği şu mantıkla çalışır: - **X**, seçilen tarihte başlangıç durumuna giren kullanıcı sayısı olsun (ör. yüklemeler). - **Y**, bu kullanıcılar arasından hedef duruma ulaşanların sayısı olsun (ör. deneme başlatmalar). - Dönüşüm oranı şu şekilde hesaplanır: **Dönüşüm = (Y / X) × 100%** :::note Grafikteki tarih, kullanıcıların başlangıç durumuna (X) girdikleri ana, yani dönüşüm için uygun hale geldikleri ana karşılık gelir. ::: Her dönüşümün açıklamasını ve referans olması açısından örneklerini aşağıda bulabilirsiniz. ### Kurulum -> Ücretli \{#install---paid\} Bu metrik, belirli bir tarihte uygulamayı yükleyen kullanıcıların kaçte kaçının sonunda ilk aboneliklerini satın aldığını gösterir. <details> <summary>Nasıl çalışır?</summary> **Tanımlar**: - **X** = Seçilen tarihteki kurulum sayısı (kurulum sırasında herhangi bir ürün seçilmediğinden tüm ürünler için aynıdır). - **Y** = Bu kullanıcılardan sonunda ilk aboneliğini satın alanların sayısı (deneme sürümü olan veya olmayan). **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 kurulum gerçekleşti. - 8 Ocak'a kadar bu kullanıcıların 20'si abonelik satın aldı. - 8 Ocak'ta, 1 Ocak'ın dönüşüm oranı = (20 / 100) × %100 = %20 - 1 Şubat'a kadar, 1 Ocak kurulum grubundan 30 kullanıcı daha abonelik satın aldı. - 1 Şubat'ta, 1 Ocak'ın dönüşüm oranı = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak'ta uygulamayı yükleyen kullanıcıların %50'sinin, günümüze kadar ücretli aboneliğe dönüştüğü anlamına gelir. </details> ### Yükleme -> Deneme \{#install---trial\} Bu metrik, belirli bir tarihte uygulamayı yükleyen ve sonunda deneme başlatan kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihteki yükleme sayısı (yükleme anında herhangi bir ürün seçilmediğinden tüm ürünler için aynıdır). - **Y** = Bu kullanıcılardan herhangi bir zamanda deneme başlatanların sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 yükleme gerçekleşti. - 8 Ocak'a kadar bu kullanıcıların 20'si deneme başlatmıştı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × %100 = %20 - 1 Şubat'a kadar, 1 Ocak yükleme grubundan 30 kullanıcı daha deneme başlatmıştı. - 1 Şubat'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak'ta uygulamayı yükleyen kullanıcıların %50'sinin şu ana kadar deneme başlattığı anlamına gelir. </details> ### Paywall görüntülemesi -> Deneme süresi \{#paywall-view---trial\} Bu metrik, paywalli gördükten sonra deneme süresini başlatan kullanıcı sayısını izler. <details> <summary>Nasıl çalışır?</summary> **Tanımlar**: - **X** = Seçilen tarihte paywalli görüntüleyen kullanıcı sayısı. - **Y** = Daha sonra herhangi bir zamanda deneme süresini başlatan kullanıcı sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 paywall görüntülenmesi gerçekleşti. - 8 Ocak'a kadar bu kullanıcılardan 20'si deneme süresini başlattı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × 100% = %20 </details> - 1 Şubat'a kadar 30 kullanıcı daha denemeyi başlattı. - 1 Şubat'ta, 1 Ocak'ın dönüşümü = ((20 + 30) / 100) × 100% = 50% Bu, 1 Ocak'ta paywall gören kullanıcıların %50'sinin, şu ana kadar denemeyi başlattığını gösteriyor. ### Paywall görüntüleme -> Ödeme yapıldı \{#paywall-view---paid\} Bu metrik, bir paywall gördükten sonra kaç kullanıcının satın alma yaptığını takip eder. <details> <summary>Nasıl çalışır</summary> **Varsayalım**: - **X** = seçilen tarihte bir paywall görüntüleyen kullanıcı sayısı. - **Y** = daha sonra herhangi bir zamanda satın alma yapan kullanıcı sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 paywall görüntülemesi gerçekleşti. - 8 Ocak'a kadar bu kullanıcıların 20'si satın alma yaptı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × 100% = %20 </details> - 1 Şubat'a kadar 30 kullanıcı daha satın alma yaptı. - 1 Şubat'ta, 1 Ocak için dönüşüm oranı = ((20 + 30) / 100) × 100% = %50 Bu, 1 Ocak'ta paywall gören kullanıcıların %50'sinin şimdiye kadar satın alma yaptığını gösteriyor. ### Deneme -> Ücretli \{#trial---paid\} Bu metrik, belirli bir tarihte deneme başlatan ve daha sonra ilk aboneliğini satın alan kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihte başlatılan deneme sayısı. - **Y** = Bu kullanıcılardan deneme süresi sonrasında abonelik satın alanların sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 deneme başlatıldı. - 8 Ocak'a kadar bu kullanıcılardan 20'si abonelik satın aldı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × 100% = %20 </details> - 1 Şubat itibarıyla, 1 Ocak deneme grubu kullanıcılarından 30'u daha aboneliğe geçti. - 1 Şubat'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × 100% = 50% Bu, 1 Ocak'ta deneme başlatan kullanıcıların %50'sinin, güncel ana kadar ücretli aboneliğe dönüştüğü anlamına gelir. ### Ücretli -> 2. Dönem \{#paid---2nd-period\} Bu metrik, aboneliğini ilk ödemeden sonra yenileyen kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = seçilen tarihteki ilk abonelik sayısı. - **Y** = herhangi bir zamanda ikinci döneme geçiş yapan kullanıcı sayısı (genellikle bir abonelik döngüsünün ardından; ek süre yenilemelerini de içerir). - **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 ilk abonelik gerçekleşti. - 8 Ocak'a kadar bunların 20'si yenilendi. - 8 Ocak itibarıyla, 1 Ocak için dönüşüm = (20 / 100) × %100 = %20 - 1 Şubat'a kadar, o gruptan 30 kullanıcı daha yeniledi. - 1 Şubat itibarıyla, 1 Ocak için dönüşüm = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak'ta ilk abonelik ödemesini yapan kullanıcıların %50'sinin şu ana kadar ikinci bir dönem için yenilediğini gösterir. </details> ### 2. Dönem -> 3. Dönem \{#2nd-period---3rd-period\} Bu metrik, ikinci abonelik döneminden sonra kaç kullanıcının yeniden yenileme yaptığını izler. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = seçilen tarihte ikinci dönem abonelik sayısı. - **Y** = daha sonra herhangi bir zamanda üçüncü dönem için yenileme yapan kullanıcı sayısı (genellikle bir sonraki faturalandırma döngüsünden sonra; ek süre yenilemeleri dahil). **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 ikinci dönem abonelik mevcuttu. - 8 Ocak'a kadar bu kullanıcıların 20'si yenileme yapmıştı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × %100 = %20 - 1 Şubat'a kadar 30 kullanıcı daha yeniledi. - 1 Şubat'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak'ta ikinci abonelik dönemine giren kullanıcıların %50'sinin, şu ana kadar üçüncü dönemi yenilediğini gösterir. </details> ### 3. Dönem -> 4. Dönem \{#3rd-period---4th-period\} Bu metrik, üçüncü abonelik döneminin ardından yenileme yapan kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihte üçüncü dönem abonelik sayısı. - **Y** = Daha sonra herhangi bir zamanda dördüncü dönem için yenileme yapan kullanıcı sayısı (genellikle bir faturalandırma döngüsü sonrasında; ek süre yenilemeleri dahil). **Formül**: Dönüşüm = (Y / X) × %100 **Örnek**: - 1 Ocak'ta 100 üçüncü dönem aboneliği mevcuttu. - 8 Ocak'a kadar 20 kullanıcı yenileme yapmıştı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × %100 = %20 - 1 Şubat'a kadar 30 kullanıcı daha yeniledi. - 1 Şubat'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak'ta üçüncü abonelik dönemine giren kullanıcıların %50'sinin, şu ana kadar dördüncü döneme yenilediği anlamına gelir. </details> ### 4. Dönem -> 5. Dönem \{#4th-period---5th-period\} Bu metrik, dördüncü abonelik döneminden sonra yenileyen kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihte dördüncü dönem abonelik sayısı. - **Y** = Daha sonra herhangi bir zamanda beşinci dönem için yenileyen kullanıcı sayısı (genellikle bir faturalama döngüsü sonra; ek süre yenilemeleri dahil). **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 adet dördüncü dönem abonelik vardı. - 8 Ocak'a kadar 20 kullanıcı yenileme yaptı. - 8 Ocak'ta, 1 Ocak için dönüşüm = (20 / 100) × 100% = 20% - 1 Şubat'a kadar 30 kullanıcı daha yeniledi. - 1 Şubat'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × 100% = 50% Bu, 1 Ocak'ta dördüncü abonelik dönemine giren kullanıcıların %50'sinin, şu ana kadar beşinci dönemi için yenilediği anlamına gelir. </details> ### 6 Ay + Bu metrik, ilk aboneliklerinden itibaren 6 aydan daha uzun süre abone kalan kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihteki ilk kez abonelik sayısı. - **Y** = Bu kullanıcılardan, orijinal abonelik tarihinden 6 ay sonra en az bir kez yenileme yapanların sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 ilk kez abonelik gerçekleşti. - Temmuz'un ilk haftasında, bunlardan 20'si yenileme yaptı (örneğin haftalık aboneliklerinin 25. haftasında). - 8 Temmuz'da, 1 Ocak için dönüşüm = (20 / 100) × 100% = 20% - 1 Ağustos'a kadar, 30 kişi daha 6 ay sonra yeniledi. - 1 Ağustos'ta, 1 Ocak için dönüşüm = ((20 + 30) / 100) × 100% = 50% Bu, 1 Ağustos itibarıyla 1 Ocak'ta abone olan kullanıcıların %50'sinin 6 ayı aşkın süre aboneliğini koruduğu anlamına gelir. </details> ### 1 Yıl + \{#1-year-\} Bu metrik, ilk abonelik tarihinden itibaren 12 aydan daha uzun süre abone kalan kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - **X** = Seçilen tarihte gerçekleşen ilk abonelik sayısı. - **Y** = Bu kullanıcılardan, orijinal abonelik tarihinden 12 ay sonra en az bir kez yenileme yapanların sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak 2021'de 100 ilk abonelik gerçekleşti. - Ocak 2022'nin ilk haftasına kadar bunlardan 20'si yenileme yaptı. - 8 Ocak 2022'de dönüşüm = (20 / 100) × %100 = %20 - 1 Şubat 2022'ye kadar 30 kişi daha 12 ay sonra yeniledi. - 1 Şubat 2022'de dönüşüm = ((20 + 30) / 100) × %100 = %50 Bu, 1 Ocak 2021'de abone olan kullanıcıların %50'sinin bir yıldan fazla aktif kaldığı anlamına gelir. </details> ### 2 Yıl + \{#2-years-\} Bu metrik, ilk ödeme tarihinden itibaren 24 aydan fazla aboneliğini sürdüren kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - X = seçilen tarihteki ilk kez abonelik sayısı. - Y = orijinal abonelik tarihinden itibaren 24 ay sonra en az bir kez yenileme yapan bu kullanıcıların sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak 2020'de 100 ilk kez abonelik gerçekleşti. - Ocak 2022'nin ilk haftasında bunların 20'si yenileme yapmıştı. - 8 Ocak 2022'de dönüşüm = (20 / 100) × 100% = %20 - 1 Şubat 2022'ye kadar 30 kişi daha 2 yıl sonra yeniledi. - 1 Şubat 2022'de dönüşüm = ((20 + 30) / 100) × 100% = %50 Bu, 1 Ocak 2020'de abone olan kullanıcıların %50'sinin 1 Şubat 2022 itibarıyla 2 yılın ardından hâlâ aktif olduğu anlamına gelir. </details> ### Ek Süre -> Ödendi \{#grace-period---paid\} Bu metrik, [abonelik ek süresine](grace-period) giren ve sorunu ek süre bitmeden *önce* çözen kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - X = ek süreye giren abone sayısı. - Y = ek süre dolmadan aboneliğini yenileyen kullanıcı sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak 2025'te 100 kişinin aboneliği otomatik olarak yenilenemedi. Bu kişiler, 17 Ocak'ta sona erecek 16 günlük bir ek süreye girdi. - 50 kişi, 1 Ocak ile 17 Ocak arasında ödeme bilgilerini güncelledi ve abonelikleri başarıyla yenilendi. - 17 Ocak 2025'te dönüşüm = (50 / 100) × %100 = %50 </details> ### Ödeme sorunu -> Ödendi \{#billing-issue---paid\} Bu metrik, [ödeme sorunuyla](/billing-issue) karşılaşan ve fatura döngüsü sona ermeden önce ödemeye devam eden kullanıcıların yüzdesini gösterir. <details> <summary>Nasıl çalışır</summary> **Tanımlar**: - X = ödeme sorunuyla karşılaşan abone sayısı. - Y = ödeme sorunu ile fatura döngüsünün sonu arasındaki sürede aboneliğini yenileyen kullanıcı sayısı. **Formül**: Dönüşüm = (Y / X) × 100% **Örnek**: - 1 Ocak'ta 100 abonenin aboneliği otomatik olarak yenilenemedi ve bu kullanıcılar ödeme sorunuyla karşılaştı. - Not: Ek süre etkinleştirilmişse, ödeme sorunu durumu yalnızca ek süre sona erdikten sonra başlar. Bu örnekte ek sürenin 1 Ocak'ta sona erdiğini varsayalım. - 8 Ocak'a kadar bu kullanıcıların 10 tanesi ödeme sorununu çözerek aboneliğini yeniledi. - 8 Ocak'ta, 1 Ocak için dönüşüm = (10 / 100) × %100 = %10 - 31 Ocak'a kadar (fatura döneminin sonu) 10 kullanıcı daha aboneliğini yeniledi. - 31 Ocak'ta, 1 Ocak için dönüşüm = ((10 + 10) / 100) × %100 = %20 Bu, 1 Ocak'ta fatura sorunu durumuna giren kullanıcıların %20'sinin sorunu çözüp fatura döngüsü sona ermeden yenileme yaptığını gösterir. </details> ## Gruplama ve zaman aralıkları \{#grouping-and-time-ranges\} Dönüşüm seçildiğinde analizin nesnesi grafiktir. Dönüşüm yüzdesinin zaman içinde nasıl değiştiğini gösterir. Tarih seçici kullanılarak zaman dilimi için hızlı seçenekler belirlenebilir. Grafik genellikle birkaç eğri içerir. Bunların beş tanesi gruplandırma listesinde varsayılan olarak seçilidir; grafiğin sağındaki alanda onay kutularını işaretleyerek seçimi değiştirebilirsiniz. Sayfayı ilk açtığınızda varsayılan gruplandırma olarak ürün süresi seçilir. Ayarlarınız önbelleğe kaydedilir ve bir sonraki ziyaretinizde en son seçtiğiniz grup görüntülenir. Aşağıdaki gruplandırmalar mevcuttur: - Ürün - Ülke - Mağaza - Paywall - Süre - Marketing attribution Seçilen tarih aralığı herhangi bir sonuç göstermek için yeterli değilse, ilgili bir tarihi öneren ve tarih aralığını otomatik olarak ayarlama seçeneği sunan bir bildirim görebilirsiniz; bu işlemi tek tıklamayla yapabilirsiniz. ## Tablo görünümü, filtreler ve CSV dışa aktarma \{#table-view-filters-and-csv-export\} Eğrilerin karşılaştırması genel bir tablo sunar; daha ayrıntılı bilgi için grafiğin altındaki tablo görünümünü kullanabilirsiniz. Tablo, grafikle senkronize çalışır; bir sütunun üzerine geldiğinizde ilgili açılır pencereyi eğriler üzerinde görebilirsiniz. Yukarıda bahsedilen gruplama hem grafikleri hem de tabloyu etkiler. Ürüne göre hızlı filtre uygulayabilir ya da Ürün, Ülke, Mağaza, Süre ve Attribution gibi gelişmiş filtrelerden yararlanabilirsiniz. Sayılarla istediğiniz şekilde çalışabilmenin önemli olduğunu biliyoruz. Bu yüzden kontrol panelinin sağında, huni verilerini CSV olarak dışa aktarmanızı sağlayan bir düğme bulunuyor. Ardından bu dosyayı Excel veya Google Sheets'te açabilir ya da tercih ettiğiniz ortamda analiz ve tahmin çalışmalarınızı sürdürmek için kendi analitik sisteminize aktarabilirsiniz. :::important Uygulamanız indirimli komisyon programına kayıtlıysa Adapty'yi bilgilendirin. Doğru hesaplamalar için [Küçük İşletme Programı](app-store-small-business-program) ve [İndirimli Hizmet Ücreti programı](google-reduced-service-fee) durumunuzu [uygulama ayarlarında](general) belirtin. ::: --- # File: reports --- --- title: "Raporlar" description: "Uygulama gelirini ve kullanıcı davranışını analiz etmek için Adapty'de ayrıntılı abonelik raporları oluşturun." --- Gelir, churn oranı, aktif aboneler, aktif denemeler ve daha fazlası dahil olmak üzere [Grafikler](charts)'de bulunan metriklerin aynısını doğrudan gelen kutunuza alın. Bu raporlar günlük, haftalık veya aylık olarak gelebilir ve en son dönemin bir öncekiyle karşılaştırmalı dinamiklerini gösterir. **[Genel Bakış](https://app.adapty.io/overview)** sayfanızda yapılandırdığınız ayarlara —metrikler, sıraları, raporlama saat dilimi ve gelir türü— göre raporlardaki verileri gönderiyoruz. Raporlarınız için istediğiniz ayrıntı düzeyini seçebilirsiniz: özet veya uygulama bazlı. Özet rapor, tüm uygulamalarınıza (veya seçtiğiniz bir alt kümeye) ait verilerin bir araya getirildiği tek bir e-postadır. Uygulama bazlı rapor ise yalnızca seçilen tek bir uygulamaya ait verileri içerir. Tüm uygulamalar için özet raporları, yakın zamanda yayımlanan veya öncelikli uygulamalar ile bizzat sorumlu olduğunuz uygulamalar için ise uygulama bazlı raporları etkinleştirmenizi öneririz. Seçilen ayrıntı düzeyinden bağımsız olarak, e-posta raporları yerel saat diliminizde sabah 9'da gelen kutunuza ulaşır: günlük raporlar her gün, haftalık raporlar Pazartesi günleri, aylık raporlar ise ayın ilk günü gönderilir. Her rapor, önceki dönemle karşılaştırmalar içeren güncel verileri kapsar (örneğin, günlük rapor dün ve önceki günün verilerini karşılaştırır; haftalık rapor geçen hafta ile ondan önceki haftanın verilerini karşılaştırır vb.). Hangi raporları seçerseniz seçin, en güncel ve doğru bilgileri doğrudan gelen kutunuza alacağınızdan emin olabilirsiniz. ## Raporları etkinleştirin \{#enable-reports\} 1. Adapty üst menüsünde [**Account**](https://app.adapty.io/account) bölümünü açın. 2. **Email reports** bölümü altında, almak istediğiniz rapor türlerini seçin – günlük, haftalık ve/veya aylık. 2. Her rapor türünü ilgili uygulamaları seçerek özelleştirin. Bunun için **Edit** düğmesine tıklayın. 3. Rapor penceresinde dahil etmek istediğiniz uygulamaları seçin. 4. Son olarak, seçimlerinizi uygulamak için **Save changes** düğmesine tıklayın. ## Saat diliminizi ayarlayın \{#set-your-time-zone\} 1. Adapty ana menüsünde [**Overview**](https://app.adapty.io/overview) bölümünü açın. 2. **Edit** düğmesine tıklayın ve saat diliminizi seçin. 3. Kaydetmek için **Done** düğmesine tıklayın. --- # File: discrepancies-and-troubleshooting --- --- title: "Veri tutarsızlıklarını giderme" description: "Farklı kaynaklardaki veri sapmalarının nedenini bulun" --- Adapty kullanıcıları, farklı kaynaklardan gelen benzer veri kümelerini karşılaştırırken **tutarsızlıklarla** karşılaşabilir. Bu durum özellikle şunları karşılaştırırken ortaya çıkabilir: * Adapty grafikleri ile mağaza raporları * Adapty grafikleri ile üçüncü taraf grafikleri * Adapty içindeki farklı grafikler ## Sorun giderme algoritması \{#troubleshooting-algorithm\} Adapty ile diğer platformlar arasındaki veri farklılıklarının büyük çoğunluğu beklenen ve normal bir durumdur. Bunun nedeni, **farklı kaynakların aynı veriyi farklı şekillerde işlemesidir**. Bazen ise bu farklılıklar **Adapty yapılandırmanızdaki bir sorunun** işareti olabilir. Verilerinizin platformlar arasında farklılık gösterdiğinden şüpheleniyorsanız yapılacak en iyi şey, [ham verileri dışa aktarmak](export-analytics-api-requests) ve **dosyaları karşılaştırmaktır**. * Mağazalar bile veri işleme ve sunumla ilgili sorunlar yaşayabilir. En doğru karşılaştırma için mağazaların **ham işlem verilerine** erişin. * Adapty'yi başka bir analitik platformla karşılaştırırken, mağaza işlem raporlarını doğruluk kaynağı ve karşılaştırma noktası olarak kullanın. * Tutarsızlıkları sınırlı bir veri setiyle tespit etmek daha kolaydır. Az miktarda veriyi karşılaştırın; belirli bir ürüne ve tek bir güne odaklanın. * Tutarsızlığınızın **fiyatlandırmadan** mı yoksa **etkinlik sayısından** mı kaynaklandığını belirleyin. Fiyatlandırma sorunları [ürün güncellemesiyle](#product-pricing) düzeltilebilir. Etkinlik sorunları [sunucu tarafı sorunlarına](#issues-with-server-notifications-and-rtdn) işaret edebilir. * Gelen etkinlikleri izlemek için [etkinlik akışını](event-feed) inceleyin; beklenmedik davranışlar fark edebilirsiniz. Verinin nerede ayrıştığını belirledikten sonra aşağıdaki yaygın nedenlere bakabilirsiniz: ## Sunucu bildirimleri ve RTDN ile ilgili sorunlar \{#issues-with-server-notifications-and-rtdn\} Mağaza bağlantılarını doğru yapılandırmadıysanız Adapty gerekli olay verilerini alamaz. Bu durum özellikle doğrudan kullanıcı etkileşimi olmadan gerçekleşen olayları etkiler; abonelik yenilemeleri, ödeme sorunları vb. Sunucudan sunucuya yapılandırmayı mümkün olan en kısa sürede tamamlayın ([App Store](enable-app-store-server-notifications) | [Play Store](enable-real-time-developer-notifications-rtdn)) ve mağazaların bağlantıyı kurması için [bekleyin](#data-delays). Eksik App Store Connect verilerini Adapty'ye [manuel olarak yükleyebilirsiniz](importing-historical-data-to-adapty). ## Eksik veri \{#missing-data\} ### Güncel olmayan uygulama sürümü kullanan kullanıcılar \{#users-with-out-of-date-app-versions\} Bazı kullanıcılarınız Adapty SDK'sı içermeyen eski bir uygulama sürümü kullanıyorsa, Adapty bu kullanıcıların verilerini alamaz. Bu nedenle Adapty ile diğer kaynakların rakamları farklılık gösterir. ### Entegrasyon sorunları \{#integration-issues\} Bazı Adapty entegrasyonları (örneğin Adjust veya AppsFlyer), çalışabilmek için uygulamaya ek kod eklenmesini gerektirir. Adapty Kontrol Paneli'ni yapılandırıp uygulamanızı güncellemezseniz, gerekli veriler Adapty'de görünmez. ### Eksik geçmiş veriler \{#missing-historical-data\} Adapty'nin uygulamanızın geçmiş verilerine erişimi yoktur; bu verileri [manuel olarak içe aktarmanız](importing-historical-data-to-adapty) gerekir. Bir grafiğin [zaman aralığı](controls-filters-grouping-compare-proceeds#set-the-date-range) Adapty'yi entegre etmeden önceki bir tarihe uzanıyorsa ve geçmiş verilerinizi içe aktarmadıysanız, grafik değerleri diğer kaynaklardan farklı çıkacaktır. ## Veri gecikmeleri \{#data-delays\} Adapty, uygulamanızın ekonomisini neredeyse gerçek zamanlı olarak analiz etmeyi hedefler. Aşağıdaki kısıtlamalar ve istisnalar geçerlidir: * Adapty'yi ilk entegre ettiğinizde veriler hemen görünmeyebilir. * Üçüncü taraf bir platformla entegrasyonu etkinleştirdiğinizde, verilerin tamamen senkronize edilmesi biraz zaman alabilir. * Adapty mağaza verilerini aldıktan sonra, bunların işlenip Analytics sayfasında görüntülenmesi **15-30 dakika** daha sürer. * Dahil olan değişken sayısı nedeniyle Adapty ile üçüncü taraflar arasındaki veri alışverişi **her zaman anlık olmayabilir**. * Bazı gelişmiş metriklere ilişkin hesaplamalar (örneğin [kohort tahminleri](predicted-ltv-and-revenue)) belirli miktarda veri gerektirir. Adapty bu hesaplamaları ancak yeterli veriyi topladığında gerçekleştirir. ## Zaman ve takvim \{#time-and-calendar\} #### Tarihler ve saat dilimleri \{#dates-and-timezones\} Algılanan veri tutarsızlıklarının en yaygın nedenlerinden biri, saat dilimi ayarlarındaki farklılıktır. Adapty günleri `UTC` saat dilimine göre sayar. Başka bir platform farklı bir saat dilimi kullanıyorsa hesaplamalar farklı olacaktır. Ölçeği büyüttükçe fark azalır. Her uygulama için [saat dilimi ayarını değiştirebilirsiniz](general#3-reporting-timezone). #### Apple mali takvimi \{#the-apple-fiscal-calendar\} Apple, satış dönemlerini ve ödeme tarihlerini belirlemek için kendi [muhasebe takvimini](https://adapty.io/apple-fiscal-calendar/) kullanır. Takvimteki her "ay" **4 veya 5 haftadan** oluşur ve **komşu takvim aylarından günler içerebilir**. Ödemeler genellikle satış dönemi bittikten 30–45 gün sonra yapılır. Örneğin "Ocak 2026" satış dönemi, takvim ayının başından 4 gün önce, 28 Aralık 2025'te başlar. Bu dönem için tahmini ödeme tarihi 5 Mart'tır. Apple ödeme raporlarındaki verileri takvim aylarıyla karşılaştırmayın. Bunun yerine, gerekli satış dönemine karşılık gelen [özel bir tarih aralığı](controls-filters-grouping-compare-proceeds#set-the-date-range) seçin. #### İşlem tarihleri \{#transaction-dates\} Bazı hizmetler (örneğin AppsFlyer), işlemleri görüntülerken [kohort](analytics-cohorts) kuralları uygulayabilir ve işlemleri gerçekleştikleri tarihe değil, uygulamanın yüklenme tarihine atfedebilir. ## Gelir hesaplama \{#revenue-calculation\} ### Ücretler ve vergiler [Ayara](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) bağlı olarak Adapty grafikleri **brüt geliri**, **mağaza komisyonu düşüldükten sonraki geliri** veya **mağaza komisyonu ve vergi düşüldükten sonraki geliri** gösterebilir. Bazı mağazalar ve üçüncü taraf platformlar, brüt geliri gösterme ya da vergileri otomatik olarak düşme özelliğine sahip olmayabilir. İki farklı gelir grafiği arasında bir tutarsızlık görürseniz, karşılaştırmanın geçerli olup olmadığını kontrol edin. ### İptaller ve iadeler \{#cancellations-and-refunds\} Farklı platformlar iade verilerini farklı şekillerde gösterir. Adapty iadeleri negatif gelir olarak kabul eder. Bir kullanıcı abone olup ertesi gün iade talep ederse, her iki etkinlik de Adapty grafiklerinde ayrı günlerde yansıtılır. Diğer platformlar iade tutarını orijinal işlemden düşebilir. ## Sandbox satın alımları \{#sandbox-purchases\} [Etkinlik akışı](event-feed), sandbox hesapları tarafından yapılan satın alımları gösterir; analitik grafikleri göstermez. Ancak geçmiş içe aktarma verileriniz sandbox satın alımları içeriyorsa, Adapty bunları ayırt edemez ve grafikleri geçmiş sandbox satın alımlarını yansıtır. ## Kurulumlar ve indirmeler \{#installs-and-downloads\} Mağazalar (özellikle Apple App Store) kullanıcı indirmelerini doğrudan takip edebilir. İstatistikleri, uygulamanın yüklendiği ancak hiç başlatılmadığı durumları da içerebilir. Adapty, [kurulum tanımınızdan](general#4-installs-definition-for-analytics) bağımsız olarak yalnızca kullanıcı uygulamayı başlattığında kurulumu kaydedebilir. ## Ülke ve mağaza \{#country-and-store\} Doğru raporlama sağlamak için Adapty, kullanıcının ülkesini IP adresinden [çıkarabilir](controls-filters-grouping-compare-proceeds#filter-and-group-data). Mağazalar ise indirmeleri ve satın almaları her zaman belirli bir uygulama mağazasına atfeder. İkisi arasında net bir ayrım yapmanız gerekiyorsa `Country by store account` özelliğiyle [yeni bir kullanıcı segmenti oluşturabilir](segments) ve [analitikleri segmente göre filtreleyebilirsiniz](controls-filters-grouping-compare-proceeds#filter-and-group-data). ## Ürün fiyatlandırması \{#product-pricing\} Yanlış ürün fiyatlandırması gelir tutarsızlığına yol açıyorsa, fiyatı değiştirmek geçmiş işlemleri geriye dönük olarak düzeltmez. Mevcut işlemlerin fiyatlarını değiştirmek için doğru verileri içe aktararak bunları zorla geçersiz kılmanız gerekir. Bir kullanıcı fiyat değişikliğinin ardından eski bir satın alımı geri yüklediğinde, Apple satın alımın değerini yanlış raporlayabilir. Adapty'nin doğru değeri yansıtması için geçmiş veriyi içe aktarmanız gerekir. ## Attribution çakışmaları \{#attribution-conflicts\} Adapty her işlem için [yalnızca tek bir attribution kaynağı](attribution-integration#prevent-data-issues) kullanabilir. Bu veriyi sonradan geçersiz kılamazsınız. Kurulumunuz birbiriyle çelişen birden fazla attribution sağlayıcısı içeriyorsa, iki farklı platformdaki aynı işlem iki farklı trafik kaynağına sahipmiş gibi görünebilir. ## Terminoloji farklılıkları \{#differences-in-terminology\} Farklı platformlar aynı kavram için farklı isimler kullanabilir. [Gelirle](#fees-and-taxes) ilgili metrikler platformdan platforma farklı adlar taşır: | Adapty | App Store Connect | Google Play Console | |--------|-------------------|----------------------| | **Brüt gelir (Gross revenue)** | Sales | Gross Revenue | | **Mağaza komisyonu sonrası gelir (Proceeds after store commission)** | N/A | N/A | | **Mağaza komisyonu ve vergi sonrası gelir (Proceeds after store commission and taxes)** | Proceeds | Earnings | | **ARPPU** | Proceeds per paying user | ARPPU | Diğer metrikler de tanım bakımından farklılık gösterebilir: - **Abonelikler**: - Adapty, yeni denemeleri abonelik olarak saymaz. [Yeni bir abonelik](reactivated-subscriptions) her zaman finansal bir işlemle başlar. - Google Play Console gibi diğer platformlar, ilk ödeme yapılmadan önce bile **her denemeyi yeni bir abonelik olarak sayabilir**. - **Retention**: - Adapty, retention'ı abonelik yenilemelerinin sayısına göre ölçer. - App Store Connect, bir kullanıcının belirtilen gün uygulamayı açması durumunda kullanıcıyı elde tutulmuş sayar. Aboneliği olmayan bir kullanıcı bu metriğe dahil edilirken, o gün uygulamayı açmayan aboneli kullanıcı dahil edilmez. - Google Play Console'un "Retained Installers" metriği, uygulamanın kullanıcının cihazında yüklü kaldığı gün sayısına göre retention'ı ölçer. Uygulamayı açmayan kullanıcılar da bu metriğe dahil edilir. ## Yeni abonelikler metriği ile `subscription_started` olayı karşılaştırması \{#new-subscriptions-metric-vs-the-subscription_started-event\} [Yeni abonelikler](reactivated-subscriptions) metriği ile `subscription_started` [entegrasyon olayı](events) farklı şeyleri sayar, bu nedenle toplamları eşleşmez. Metrik, hem deneme süresi olmadan yapılan ilk satın almalarını hem de deneme-ücretli dönüşümlerini sayar. `subscription_started` olayı yalnızca deneme süresi olmadan yapılan ilk satın almalar için tetiklenir; bir deneme ücretli aboneliğe dönüştüğünde Adapty bunun yerine `trial_converted` olayını gönderir. Sonuç olarak, uygulamanızda deneme dönüşümleri olduğunda Yeni abonelikler sayısı, `subscription_started` olay sayısından daha yüksek olur. --- # File: predicted-ltv-and-revenue --- --- title: "Kohortlarda tahminler" description: "LTV ve geliri tahmin etmek için Adapty'nin tahmine dayalı analitiğini kullanın." --- Adapty Tahminleri, aşağıdaki soruları yanıtlamanıza yardımcı olmak için tasarlanmıştır: 1. Kullanıcı kohortlarınızın tahmini yaşam boyu değeri (LTV) nedir? 2. Hangi kohortlar gelecekte en yüksek geliri elde etme olasılığına sahiptir? 3. Tahmini geri dönüşü göz önünde bulundurarak ne kadar yatırım yapabilirsiniz? Adapty Predictions ile gelir ve büyüme hakkında veriye dayalı kararlar alabilirsiniz. Adapty'nin tahmin modeli, uygulamanızın kullanıcı kohortlarının uzun vadeli gelir potansiyelini tahmin eder. Her kohort için gelirin, ödeme yapan abone sayısının ve ortalama LTV'nin zaman içinde nasıl gelişeceğini öngörür. Bu sayede kullanıcı edinme, pazarlama stratejileri ve ürün geliştirme konularında bilinçli kararlar alabilirsiniz. Adapty, ödeme yapan abonelerin kohortları için tahmini yaşam boyu değer (LTV) ve tahmini gelir sunar. Tahminler, kohort analizi sayfasında kohort oluşturulduktan sonra 3, 6, 9, 12, 18 ve 24. aylar için gösterilir. Geçmişi çok sınırlı uygulamalar için model, uygulamalar arası ortalamalara geri döner; bu nedenle yeni uygulamalara yönelik tahminler, söz konusu uygulamanın kullanıcı davranışını tam olarak yansıtmayabilir. ## Modelin çalışma şekli \{#how-the-model-works\} Adapty'nin tahmin modeli, gelecekteki geliri ve LTV'yi öngörmek için geçmiş kohort verilerindeki tutma kalıplarını kullanır. Her uygulama ve abonelik türü kombinasyonu için model, ödeme yapan abonelerin ve toplam gelirin her yenileme döneminden bir sonrakine nasıl değiştiğini ölçer. Uygulamanın geçmiş kohortlarına dayanarak iki tutma oranı hesaplar; biri aboneler için, diğeri gelir için. Bu oranlar daha sonra yeni kohortlara uygulanarak kohort oluşturulduktan sonraki 3, 6, 9, 12, 18 ve 24 aylık büyümelerini tahmin etmek için kullanılır. Kullanılan veriler tamamen anonimleştirilmiştir. Model, her kohort için iki değer üretir: - **Predicted revenue**: Bir kohortun seçilen ufuk dahilinde oluşturması öngörülen toplam gelir. - **Predicted LTV**: Öngörülen gelirin, kohorttaki tahmini ödeme yapan abone sayısına bölünmesiyle elde edilen değer. ### Uygulamaya özgü ve uygulamalar arası ağırlıklar \{#app-specific-and-cross-app-weights\} Varsayılan olarak, bir kohort için yapılan tahminler, o uygulamanın kendi geçmiş kohortlarından öğrenilen kullanıcı davranışını yansıtan elde tutma ağırlıklarını kullanır. Bir uygulamanın belirli bir tahmin ufku için yeterli geçmişi yoksa, Adapty aynı abonelik türündeki tüm uygulamalarda ortalaması alınmış elde tutma ağırlıklarına (cross-app fallback) geri döner. Örneğin, yalnızca altı aylık bir uygulama için yapılan 12 aylık projeksiyon, cross-app fallback kullanır. Bu fallback her ufuk için bağımsız olarak uygulanır; dolayısıyla aynı kohort, 3 aylık tahmin için uygulamanın kendi ağırlıklarını, 12 aylık tahmin için ise cross-app ağırlıklarını kullanabilir. ### Uygunluk ve Güncellemeler \{#availability-and-updates\} Tahminler, bir kohort ilk yenileme dönemini tamamladıktan sonra kullanılabilir hale gelir; bu genellikle haftalık abonelikler için oluşturulduktan bir hafta sonra, aylık abonelikler içinse yaklaşık dört hafta sonradır. Sonrasında tahminler, kohortun davranışıyla güncel kalmaları için en son işlem verileri kullanılarak her gün güncellenir. ### Sınırlamalar \{#limitations\} - **Veri kalitesi**: Alışılmadık kohort davranışları veya çok az ödeme yapan aboneye sahip kohortlar doğruluğu düşürür. 30'dan az ödeme yapan aboneye sahip kohortlar, modelin eğitim verilerinden çıkarılır. - **Yeni uygulamalar**: Yeterli geçmişi olmayan uygulamalar, uygulamanın kullanıcı davranışını yansıtmayabilecek uygulamalar arası yedek ağırlıklar kullanır. - **Kohort yaşı**: Belirli bir horizon için tahminler, kohort o horizonu aştığında gizlenir. Örneğin, 3 aylık tahminler üç aydan sonra gösterilmeyi durdurur ve 24 aydan eski kohortlar için hiçbir tahmin gösterilmez. ## Kontrol Panelinde \{#in-the-dashboard\} Tahminleri görüntülemek için Adapty kontrol panelinizde Kohort analizi sayfasına gidin. Kohortlar hakkında ayrıntılı bilgi için [Kohort analizi](analytics-cohorts) sayfasına bakın. <img src="/assets/shared/img/4d808b4-Export-1691486610612.gif" alt="Cohort Analysis page showing Predicted Revenue and Predicted LTV columns" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Predicted revenue** sütunu, bir abonelik kohortunun oluşturulmasından itibaren seçilen zaman diliminde elde etmesi beklenen tahmini toplam geliri gösterir. Bu değer, uygulamanın geçmiş kohort elde tutma verilerine dayanan Adapty'nin tahmin modeli kullanılarak hesaplanır. **Predicted LTV** sütunu, seçilen kohortdaki her bir kullanıcının tahmini yaşam boyu değerini gösterir. Bu değer, tahmini gelirin kohorttaki tahmini ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. ### Ufku seçin \{#select-the-horizon\} Tahmin ufkunu değiştirmek için **Predictions** açılır menüsünden bir değer seçin. Kullanılabilir seçenekler, kohort oluşturulduktan sonra 3, 6, 9, 12, 18 ve 24 aydır. ### Ürüne göre filtrele \{#filter-by-product\} Tahmini geliri ve LTV'yi ürüne göre filtreleyebilirsiniz. Varsayılan olarak tahminler tüm satın alma verilerinden oluşturulur; ürüne göre filtreleme ise her ürünün ne kadar katkı sağladığını gösterir. <img src="/assets/shared/img/66a9c61-Export-1691486288948.gif" alt="Ürüne göre filtrelenmiş Kohort Analizleri" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Tahminler mevcut olmadığında \{#when-predictions-are-unavailable\} Bir kohort için tahmin üretilemediğinde, Predicted Revenue ve Predicted LTV sütunlarında değerler yerine em tire (—) gösterilir. Bunun birkaç farklı nedeni olabilir: - **Kohort oluşturulmasından bu yana geçen süre yetersiz**: Tahminler yalnızca kohort ilk yenileme dönemini tamamladıktan sonra kullanılabilir hale gelir — haftalık abonelikler için yaklaşık bir hafta, aylık abonelikler için yaklaşık dört hafta. - **Kohort boyutu çok küçük**: Güvenilir bir projeksiyon üretmek için yeterli sayıda ödeme yapan abone yok. - **Alışılmadık kohort davranışı**: Kohort, modelin beklediği kalıplardan önemli ölçüde sapıyor. Daha fazla veri birikmesiyle birkaç hafta içinde bu sorun kendiliğinden çözülebilir. - **Ufuk aşıldı**: Kohort, seçilen tahmin ufkundan daha eski. Örneğin, 3 aylık tahmin üç aydan sonra gizlenir, 12 aylık tahmin on iki aydan sonra gizlenir ve 24 aydan eski kohortlar için hiçbir tahmin gösterilmez. :::warning Tahminleri etkinleştirirken, Adapty kontrol panelinizde Gelir ve LTV için tahmin verilerinin görünür hale gelmesi için maksimum 24 saatlik bir gecikme olabileceğini unutmayın. ::: --- # File: predictions-in-ab-tests --- --- title: "A/B testlerinde tahminler" description: "A/B testlerindeki tahminlerin abonelik fiyatlandırma stratejilerini nasıl geliştirdiğini öğrenin." --- Adapty'nin A/B testi özelliği için Tahminsel Analiz dokümantasyonuna hoş geldiniz. Bu araç, çalışan A/B testlerinizin gelecekteki sonuçlarına dair içgörüler sunar ve Adapty'nin makine öğrenmesiyle desteklenen tahminleri sayesinde veriye dayalı kararlar almanızı hızlandırır 🚀 ### A/B testi tahminleri nedir? \{#what-are-ab-test-predictions\} Adapty'nin A/B Testi Tahminleri, bir A/B testinde karşılaştırılan paywallların uzun vadeli gelir potansiyelini öngörmek için gelişmiş makine öğrenmesi tekniklerinden (özellikle gradient boosting modelleri) yararlanır. Bu tahminsel model, test çalışırken gözlemlediğiniz metriklere bağlı kalmak yerine, bir yıl sonraki tahmini gelire göre en etkili paywallı seçmenizi sağlar. Bu sayede verinin birikmesini haftalar boyu beklemek zorunda kalmadan kazananı daha güvenilir ve hızlı bir şekilde belirleyebilirsiniz. ### Model nasıl çalışır? \{#how-does-the-model-work\} Model, farklı kategorilerdeki çok sayıda uygulamadan elde edilen kapsamlı geçmiş A/B testi verileriyle eğitilmiştir. Bir paywallın deney başlangıcından itibaren bir yıl içinde üreteceği geliri tahmin etmek için geniş bir özellik yelpazesini kullanır. Bu özellikler şunlardır: - Farklı dönemlerde kullanıcı işlemleri ve dönüşüm oranları - Kullanıcıların coğrafi dağılımı - Platform kullanımı (iOS veya Android) - İptal ve iade oranları - Abonelik ürünleri ve dönem uzunlukları (günlük, aylık, yıllık vb.) - Diğer işlem verisi Model ayrıca paywallardaki deneme sürelerini de hesaba katar; kullanıcıların zaten dönüşüm gerçekleştirmiş gibi geliri tahmin etmek için geçmiş dönüşüm oranlarını kullanır. Bu yaklaşım, deneme teklifleri olan ve olmayan paywalllar arasında adil bir karşılaştırma yapılmasını sağlar; çünkü aktif denemelerin gelecekte gelir getirebileceği ihtimali de hesaba katılır. ### Tahminsel P2BB, standart P2BB'den nasıl farklıdır? \{#how-is-predicted-p2bb-different-from-just-the-p2bb\} A/B testlerimizde Bayesçi yaklaşımı kullanıyoruz: temel olarak kullanıcı başına gelirin (daha doğrusu "1.000 kullanıcı başına gelir") dağılımını modelliyoruz, ardından bir dağılımın diğerinden "gerçek anlamda" daha iyi olup olmadığını ve bunun rastlantısal olmamasını hesaplıyoruz — buna En İyi Olma Olasılığı ya da P2BB diyoruz (yaklaşımımız hakkında daha fazla bilgiye [buradan](maths-behind-it) ulaşabilirsiniz). Bunu yaparken yalnızca testin çalıştığı süre boyunca biriken gelire dayandığımızı belirtmek önemlidir. Örneğin yıllık bir aboneliği haftalık bir abonelikle karşılaştıran bir test çalıştırırsanız, hangisinin daha iyi performans gösterdiğini gerçekten anlamak için çok uzun süre beklemeniz gerekir. Benzer bir durum, A/B testinde deneme aboneliklerini deneme içermeyen aboneliklerle karşılaştırdığınızda da yaşanır; çünkü kazanan dinamiklerini etkileyebilecek aktif denemeler her zaman gelir hesabının dışında kalır. İşte tahminsel modelimiz tam da burada devreye giriyor. Bir A/B testindeki mevcut gelir dağılımını alarak ve büyük bir veri setiyle eğitilerek, gelir dağılımının gelecekteki halini (yani 1 yıl sonrasını) tahmin edebiliyor. Bunu yaptıktan sonra, testi tüm yıl boyunca çalıştırsaydınız ulaşacağınız P2BB'yi yani tahminsel P2BB'yi üretiyor. Bazen tahminsel P2BB ile mevcut P2BB'nin çelişebileceğini unutmayın. Bu durumda varyasyon satırlarını aşağıdaki gibi sarı renkle vurgularız: <img src="/assets/shared/img/74577c6-CleanShot_2024-02-15_at_13.08.452x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bunu, kazananı teyit etmek için daha fazla veri biriktirmeniz ya da A/B testini daha derinlemesine incelemeniz gerektiğinin bir işareti olarak değerlendiriyoruz. Genel olarak daha fazla veriyi göz önünde bulundurduğu için mevcut P2BB yerine tahminsel P2BB'ye güvenmenizi öneririz; ancak nihai karar elbette size aittir. ### Modelin doğruluğu ve güvenilirliği \{#model-accuracy-and-certainty\} Model, %10'un biraz altında bir Ortalama Mutlak Yüzde Hata (MAPE) değeriyle yüksek düzeyde doğruluk sağlar. Bu hassasiyet düzeyi, işletmelerin veriye dayalı kararlar alırken modelin tahminlerine güvenle dayanmasına olanak tanır. Kararlılığı daha da güvence altına almak için model, üç faktöre dayanan bir "kesinlik" kriteri uygular: - Dar bir tahmin aralığı — model sonuçtan emindir - Testte yeterli miktarda abonelik ve gelir bulunması - Testin başlangıcından itibaren en az 2 haftanın geçmiş olması Bir tahmin, bu üç kriterin en az ikisi karşılandığında güvenilir sayılır. Yeni bir A/B testi başladığında, model her paywall için 1k başına yıllık gelir tahmini (ana A/B testi metriğimiz) sağlar. Tahminler yalnızca kesinlik kriterlerini karşıladıklarında görüntülenir. Veriler yetersizse model "tahmin için yetersiz veri" ibaresini gösterir. ### Sınırlılıklar ve dikkat edilmesi gerekenler \{#limitations-and-considerations\} Tahminsel modelimiz güçlü bir araç olsa da sınırlılıklarını göz önünde bulundurmak önemlidir. Modelin performansı, mevcut verilerin kalitesine ve temsiliyetine bağlıdır. Alışılmadık kohort davranışları ya da eğitim setinde yer almayan yeni uygulamalar tahmin doğruluğunu etkileyebilir. Bununla birlikte, tahminler en güncel verileri ve kullanıcı davranışlarını yansıtmak amacıyla her gün güncellenir. Bu sayede aldığınız içgörüler her zaman en güncel bilgilere dayanır. 🚧 Not: Bu araç, uzman değerlendirmenizin ve uygulamanızın kendine özgü dinamiklerine dair anlayışınızın yerini almaz; ona destek sağlar. Bu tahminleri, bilinçli kararlar vermek için diğer metrikler ve pazar bilgisiyle birlikte bir rehber olarak kullanın. --- # File: adapty-ads-manager --- --- title: "Adapty Ads Manager" description: "Apple Ads'den gerçek zamanlı analitik alın ve kampanyalarınızı yönetin ve optimize edin" --- **Adapty Ads Manager**, Apple Ads kampanyalarınızı daha verimli yönetmenizi, optimize etmenizi ve ölçeklendirmenizi sağlamak için tasarlanmış hepsi bir arada bir platformdur. Herhangi bir MMP gerektirmeksizin Apple Search Ads performansınızı kurulum, deneme, abonelik ve yaşam boyu değer gibi temel gelir metrikleriyle birleştirir. Gerçek zamanlı analizler, yapay zeka destekli tahminler ve akıllı otomasyon sayesinde Adapty Ads Manager, yorucu manuel teklif değişikliklerini, elektronik tabloları ve tahmin oyununu ortadan kaldırır; bunların yerine daha hızlı harekete geçmenizi sağlayan net içgörüler ve araçlar sunar. Adapty Ads Manager ile şunlara sahip olursunuz: - **[Genel Bakış](ads-manager-overview)**: Tüm önemli metrikler tek bakışta — harcama, gelir, ROAS, CPA ve daha fazlası — her biri günlük trend grafiğiyle birlikte - **[AI Ajanı](ads-manager-ai-agent)**: Sade dilde sorular sorun, tam hunili yanıtlar ve öneriler alın - **Gerçek zamanlı performans verileri**: Kampanyalar, reklam grupları ve anahtar kelimeler genelinde - **Uçtan uca gelir takibi**: Aramadan → kuruluma → denemeye → aboneliğe → LTV'ye kadar - **AI tahminleri ve önerileri**: Kârlı ölçeklendirme için - **Toplu yönetim**: Teklifler, bütçeler, durumlar ve yapılar için - **[Kural tabanlı otomasyonlar](ads-manager-automations)**: Anahtar kelime yaşam döngüsünün tamamını yönetin - **[Pazar İstihbaratı](ads-manager-market-intelligence)**: 50'den fazla ülkede rakip anahtar kelime stratejileri - **[CPP A/B Testleri](ads-manager-cpp-ab-tests)**: Özel ürün sayfalarını birbiriyle karşılaştırın ve en iyi performans göstereni bulun <CustomDocCardList ids={['adapty-ads-manager-get-started', 'ads-manager-overview', 'ads-manager-ai-agent', 'adapty-ads-manager-analytics', 'ads-manager-create-campaign', 'ads-manager-create-ad-group', 'ads-manager-manage-keywords', 'ads-manager-automations', 'ads-manager-market-intelligence', 'ads-manager-cpp-ab-tests']} /> ## Adapty Ads Manager'ı neden seçmelisiniz? \{#why-choose-adapty-ads-manager\} Çünkü size **piyasadaki en doğru veriyi** sunuyoruz. Native Apple Ads konsolunun veya MMP'lerin aksine, verilerimiz **gerçek zamanlı, kayıpsız ve tamamen bağlı** — trial'lara, aboneliklere ve LTV'ye, gecikme ya da attribution boşluğu olmadan. Kolay kurulumu ve sorunsuz kullanıcı deneyimiyle birden fazla araç arasında geçiş yapmak zorunda kalmadan her şeyi tek bir yerden yönetebilirsiniz. ## Başlarken \{#get-started\} Adapty Ads Manager'ı kullanmaya başlamak için [kılavuzu](adapty-ads-manager-get-started) takip edin; her şey hazır olduğunda keşfetmeye başlayabilirsiniz. --- # File: adapty-ads-manager-get-started --- --- title: "Adapty Ads Manager'a Başlarken" description: "Apple Ads'dan geçmiş verilerinizi içe aktarın ve kontrol panelinde gerçek zamanlı güncellemeler almaya başlayın" --- [Adapty Ads Manager](adapty-ads-manager), Apple Ads için optimizasyon ve analitik platformunuzdur. Bu kılavuzda, Adapty Ads Manager ile iki adımda nasıl çalışmaya başlayacağınızı öğreneceksiniz: 1. Adapty SDK'yı yükleyin ve satın alma verilerinizi takip etmesine izin verin. 2. Geçmiş verilerinizi içe aktarmak ve gerçek zamanlı güncellemeleri takip etmeye başlamak için Adapty Ads Manager'ı Apple Ads hesabınıza bağlayın. :::note Adapty Ads Manager, **App settings** içindeki [Apple Ads entegrasyonunu](apple-search-ads) kullanmaz. Adapty Ads Manager'ı kullanmak için yalnızca bu kılavuzda açıklanan kurulumu tamamlamanız yeterlidir. ::: ## 1. Adapty SDK'yı Yükleyin \{#1-install-the-adapty-sdk\} :::important Adapty Ads Manager **bağımsız bir üründür**. Paywall'larınız, abonelikleriniz veya analizleriniz Adapty tarafından yönetilmese bile kullanabilirsiniz; tüm altyapınızı Adapty'ye taşımanız gerekmez. Doğru gelir verisi almak için minimum kurulum, Adapty SDK'yı gözlemci modunda yüklemek ve Adapty'de App Store sunucu bildirimlerini etkinleştirmektir. ::: Gelir verilerinizi kampanya performansıyla ilişkilendirmek için Adapty'nin satın almalarınızı takip etmesine izin verin: 1. İlk adım, uygulama içi satın almaları zaten uygulayıp uygulamadığınıza göre değişir: - **Uygulama içi satın almaları Adapty ile zaten uyguladıysanız**, bu aşamada başka bir şey yapmanıza gerek yoktur. - **Uygulama içi satın almaları Adapty olmadan zaten uyguladıysanız** ve Adapty'ye geçmeyi planlamıyorsanız, platformunuz için Adapty SDK'yı gözlemci modunda yükleyin. Bu aşamada yalnızca SDK'yı projenize eklemeniz, gözlemci modu etkin şekilde başlatmanız ve işlemleri raporlamanız gerekir: - [iOS](implement-observer-mode) - [Android](implement-observer-mode-android) - [React Native](implement-observer-mode-react-native) - [Flutter](implement-observer-mode-flutter) - [Unity](implement-observer-mode-unity) - [Kotlin Multiplatform](implement-observer-mode-kmp) - [Capacitor](implement-observer-mode-capacitor) - **Uygulama içi satın almaları henüz uygulamadıysanız ve Adapty'yi kullanmak istiyorsanız**, satın alma işlemlerini Adapty'ye devretmek için [hızlı başlangıç kılavuzundaki](quickstart) adımları tamamlayın. 2. Gelirle ilgili güncellemeleri doğrudan App Store'dan almak için [Adapty'de App Store sunucu bildirimlerini etkinleştirin](enable-app-store-server-notifications). ## 2. Apple Ads'i Bağlayın \{#connect-apple-ads\} :::important Apple Ads'i Adapty'ye bağlamak için Apple Ads'de **Account Admin** rolüne sahip olmanız gerekir. ::: Şimdi Adapty Ads Manager hesabınızı Apple Ads hesabınıza bağlamanız gerekiyor: 1. Başlıktaki Adapty logosuna tıklayın ve **Search Ads**'i seçin. 2. **Continue with Apple**'a tıklayın. 3. Apple hesabınıza giriş yapın. 4. Adapty Ads Manager'a vermek istediğiniz erişimi seçin: - **Read and Write**: Tüm kampanya gruplarına erişim sağlar. - **Limited access**: Belirli kampanya gruplarını seçin ve yalnızca bu gruplara erişim vermek için **Read & Write** rolünü atayın. 5. **Grant access** düğmesine tıklayın. Bunun ardından Adapty, Apple Ads'teki geçmiş verilerinizi senkronize etmeye başlayacaktır. Adapty Ads Manager'ı hemen keşfetmeye başlayabilirsiniz, ancak tüm geçmiş verilerin içe aktarılması biraz zaman alacaktır. ## Sırada Ne Var \{#whats-next\} İşlem verilerinizi başarıyla senkronize ettikten sonra şunları nasıl yapacağınızı öğrenmeye devam edin: - [Kampanyalarınızı, reklam gruplarınızı ve anahtar kelimelerinizi yönetin](ads-manager) - [Kampanya performansına göre teklifleri ayarlamak için otomasyon kuralları oluşturun](ads-manager-automations) --- # File: ads-manager-overview --- --- title: "Adapty Ads Manager'da Genel Bakış" description: "Tüm önemli Apple Ads metriklerinizi tek bir yerde, her biri trend grafiğiyle birlikte görün." --- **Overview** sayfası, tüm önemli Apple Ads metriklerinizi tek bir yerde, her biri trend grafiğiyle birlikte gösterir. Varsayılan olarak, bağlı tüm uygulamalarınızın verilerini gösterir. Tek bir uygulamayı görüntülemek için başlıktaki uygulama açılır menüsünden seçim yapın. Açmak için Adapty Ads Manager'ın sol kenar çubuğundaki **Overview** bölümüne gidin. :::tip Metrikleri tek tek incelemek yerine dikkat etmeniz gerekenlerin özetini almak için [AI Agent](ads-manager-ai-agent)'ı kullanabilirsiniz. ::: ## Metrikler \{#metrics\} Her metrik, seçilen zaman aralığı için bir trend grafiğiyle birlikte bir kart olarak gösterilir. Metrik tanımları ve formüller için bkz. [Adapty Ads Manager'daki Metrikler](adapty-ads-manager-metrics). ## Görüntülenen metrikleri yapılandırma \{#configure-displayed-metrics\} **Overview** sayfasında hangi metriklerin görüneceğini değiştirmek için **Edit metrics** seçeneğine tıklayın. Buradan şunları yapabilirsiniz: - **Metrik ekleme**: **Add metric** seçeneğine tıklayın ve istediğiniz metriklerin onay kutularını işaretleyin. - **Metrik kaldırma**: **Add metric** panelinde ilgili onay kutusunun işaretini kaldırın ya da yanındaki **×** simgesine tıklayın. ## Kontroller \{#controls\} **Overview** sayfasında neyin gösterileceğini ayarlamak için üstteki kontrolleri kullanın: - **Tarih aralığı**: Hazır bir dönem seçin (**Last 7 days**, **Last 30 days**, **Last 90 days**) veya özel bir aralık girin. Tüm grafikler ve özet değerler seçilen döneme göre güncellenir. - **Grafik türü**: Yığılmış sütun, çizgi ve pasta grafik görünümleri arasında geçiş yapın. - **Gelir görüntüleme**: Gelir metriklerinin nasıl hesaplanacağını seçin: - **Gross revenue**: Herhangi bir kesinti yapılmadan önceki toplam gelir. - **Proceeds after store commission**: Apple'ın komisyonu düşüldükten sonraki gelir. - **Proceeds after store commissions and taxes**: Hem Apple'ın komisyonu hem de geçerli vergiler düşüldükten sonraki net gelir. --- # File: ads-manager-ai-agent --- --- title: "Adapty Ads Manager'da AI Agent" description: "Apple Ads hesabınız hakkında düz dilde sorular sorun ve tam dönüşüm hunisi yanıtları ve öneriler alın." --- AI Agent, Adapty Ads Manager'daki bir sohbet asistanıdır ve Apple Ads hesabınız hakkındaki soruları düz dilde yanıtlar. Gösterim, yükleme, deneme, abonelik ve gelir olmak üzere tam dönüşüm hunisini kullanır; bu sayede yalnızca tıklamalara değil, gelir ve ROAS'a odaklanarak analiz yapar. Adapty'nin yerleşik attribution özelliği, bu huni verilerini neredeyse gerçek zamanlı olarak agent'a sunar. Ajan yalnızca tavsiye niteliğindedir: hesabınızı analiz eder ve ne yapmanız gerektiğini önerir, ancak kampanyaları, teklifleri veya bütçeleri sizin adınıza değiştirmez. ## Neler sorabilirsiniz \{#what-you-can-ask\} Apple Ads hesabınızın herhangi bir bölümü hakkında agent'a soru sorabilirsiniz. Agent şunları yapabilir: - **Hesap genel bakışı**: Hesabınızda neler olduğunu özetler ve önce neye dikkat etmeniz gerektiğini gösterir. - **Düşük performanslı öğeler**: Kâr getirmeyen kampanyaları ve dönüşüm sağlamayan anahtar kelimeleri bulur. - **Bütçe**: Günlük bütçe sınırına ulaşan kampanyaları tespit eder ve bütçeyi artırıp artırmamak gerektiğini önerir. - **Teklif ve duraklatma kararları**: Teklifin artırılıp artırılmaması ya da mevcut hâlde bırakılması, kampanyanın duraklatılıp duraklatılmaması gerektiğini önerir. - **Coğrafi performans**: Hangi ülkelerin iyi, hangilerinin kötü performans gösterdiğini ortaya koyar ve bütçenin nereye kaydırılması gerektiğini gösterir. ## Örnek sorular \{#example-questions\} Ajan, bir metrik, zaman aralığı ve değerlendirdiğiniz karar adını belirttiğinizde en kullanışlı yanıtları verir. Örneğin: - Hangi anahtar kelimeler en yüksek ROAS'a sahip ve bütçeyi bunlara nasıl yeniden dağıtmalıyım? - Son 30 günde harcama yapılmış ama deneme veya aboneliğe dönüşüm olmamış anahtar kelimeler hangileri ve hangilerini duraklatmalıyım? - Günlük bütçe sınırına ulaşan ama karlılığını koruyan kampanyalar hangileri ve her birini ne kadar artırmalıyım? - Ülkelerimi ROAS ve abonelik başına maliyete göre karşılaştır — bütçeyi nereye taşımalıyım? - Bu anahtar kelimenin teklifini düşürmeli miyim, duraklatmalı mıyım yoksa daha fazla zaman mı tanımalıyım? Cevabının arkasındaki huni verilerini göster. - Hangi anahtar kelimeler ucuz kurulum sağlıyor ama ücretli aboneliğe nadiren dönüşüyor? ## AI Agent'ı Açın \{#open-the-ai-agent\} Agent'ı açmak için hesap başlığındaki **Ask AI Agent** düğmesine tıklayın. Herhangi bir şey sormadan önce agent'ın kapsamını belirlemek için bir uygulama seçin. Ardından sorunuzu yazın ve gönderin. Agent görevleri arka planda çalıştırır; dolayısıyla yanıt hazırlanırken Adapty Ads Manager'da çalışmaya devam edebilirsiniz. ## Önceki sohbetlere erişme \{#access-previous-chats\} Küçük panel yalnızca mevcut konuşmanızı gösterir. Önceki sohbetlere dönmek için panelin üst kısmındaki genişlet düğmesine tıklayarak tam ekran moduna geçin. Sol tarafta bir **Chats** listesi açılır; burada geçmiş konuşmaları arayabilir ya da **New chat** ile yeni bir konuşma başlatabilirsiniz. ## Sınırlamalar \{#limitations\} AI Ajanı yalnızca tavsiye niteliğindedir. Eylemler önerir ancak bunları sizin adınıza uygulamaz. Önerilerini gözden geçirin ve değişiklikleri [kampanya yönetimi](ads-manager-create-campaign) ile [anahtar kelimeler](ads-manager-manage-keywords) konularında kendiniz uygulayın. --- # File: adapty-ads-manager-metrics --- --- title: "Adapty Ads Manager'daki Metrikler" description: "Adapty Ads Manager'da uygulama analizlerini görüntüleyin." --- Adapty Ads Manager, kampanya performansını ve kullanıcı davranışını ölçmek için kapsamlı metrikler sunar. ## Performans \{#performance\} | Metrik | Açıklama | |--------|----------| | Spend | Kullanıcıların reklamınıza her tıklamasının maliyetinin toplamı. | | Impressions | Raporlama dönemi içinde sponsorlu reklamınızın App Store arama sonuçlarında görüntülenme sayısı. | | CPM | Bin reklam gösterimi başına ödediğiniz ortalama tutar. Ort. CPM = Spend / (Impressions / 1000) Not: CPT fiyatlandırma modeline sahip App Store Arama Sonuçları Kampanyaları için etkin CPM gösterilir. | | Taps | Raporlama dönemi içinde kullanıcıların reklamınıza tıklama sayısı. | | CPT | Reklamınıza yapılan her tıklama başına ödediğiniz ortalama tutar. Ort. CPT = Spend / Taps | | TTR | Reklamınızın aldığı toplam gösterime bölünen tıklama sayısı. TTR = Taps / Impressions * 100% | | Downloads (Total) | Raporlama dönemi içinde bir reklamdan gelen tıklama yoluyla ve görüntüleme yoluyla gerçekleşen yeni indirmeler ve yeniden indirmelerin toplam sayısı. | | Downloads (View-Through) | Reklamınızı 24 saatlik süre içinde görüntüleyen ancak tıklamayan kullanıcılardan gelen indirme ve yeniden indirme sayısı. | | Downloads (Tap-Through) | 30 günlük süre içinde reklamınıza tıklayan kullanıcılardan gelen toplam yeni indirme ve yeniden indirme sayısı. | | Avg CPA (Total) | Toplam ortalama edinim başına maliyet (CPA), toplam kampanya harcamasının raporlama dönemi içinde reklamınızı görüntüleme veya tıklama sonucu gerçekleşen toplam indirme sayısına bölünmesiyle hesaplanır. | | Avg CPA (Tap-Through) | Tıklama yoluyla ortalama edinim başına maliyet (CPA), toplam kampanya harcamasının raporlama dönemi içindeki tıklama yoluyla indirme sayısına bölünmesiyle hesaplanır. | | Download Rate (Total) | Reklamınıza yapılan tıklama veya görüntüleme sonucu gerçekleşen toplam indirmenin raporlama dönemi içindeki toplam tıklama sayısına bölünmesiyle hesaplanır. Formül: Taps > 0 ise (Total Downloads / Taps) × 100%, aksi hâlde 0% | | Download Rate (Tap-Through) | Reklamınıza yapılan tıklamalar sonucu gerçekleşen toplam indirmenin raporlama dönemi içindeki toplam tıklama sayısına bölünmesiyle hesaplanır. Formül: Taps > 0 ise (Tap-Through Downloads / Taps) × 100%, aksi hâlde 0% | | DPM (Total) | Downloads per Mille (DPM), bin gösterim başına indirme sayısıdır. Formül: Impressions > 0 ise (Total Downloads / Impressions) × 1000, aksi hâlde 0 | ## Dönüşümler \{#conversions\} :::note Gelir, ARPU, ARPPU, ARPAS, ROAS ve ROI; kullanıcı gruplarının zaman bazlı analizinde kohort metrikleri olarak da kullanılabilir. ::: | Metrik | Açıklama | |--------|----------| | Conversions | Conversions, raporlama dönemi içindeki toplam dönüşüm olayı sayısıdır. Formül: Başlatılan denemeler + Başlatılan abonelikler + Abonelik dışı satın almalar | | Conversion CR | Conversion CR (Dönüşüm Oranı), toplam indirmelerin dönüşümle sonuçlanan yüzdesidir. Formül: Total Downloads > 0 ise (Conversions / Total Downloads) × 100%, aksi hâlde 0% | | Cost per Conversion | Cost per Conversion, toplam harcamanızın dönüşüm sayısına bölünmesiyle hesaplanır. Formül: Conversions > 0 ise Spend / Conversions, aksi hâlde 0 | | Revenue | Revenue, seçilen zaman diliminde uygulama içindeki satın almalar, yenilemeler veya diğer paraya çevirme dönüşümlerinden elde edilen toplam gelirdir (mağaza komisyonu öncesi). | | ROAS | ROAS (Reklam Harcamasının Getirisi), reklamlarınızdan elde edilen gelirin reklam harcamasına bölünüp yüzde olarak ifade edilmesiyle hesaplanır. Formül: Spend > 0 ise (Revenue / Spend) × 100%, aksi hâlde 0% | | ROI | ROI (Yatırım Getirisi), harcamaya göre net kârı ölçer. Formül: Spend > 0 ise ((Revenue − Spend) / Spend) × 100%, aksi hâlde 0% | | ARPU | ARPU (Kullanıcı Başına Ortalama Gelir), kullanıcı başına ortalama gelirdir. Toplam gelirin benzersiz kullanıcı sayısına bölünmesiyle hesaplanır. $60.000 gelir / 5.000 kullanıcı = $12 ARPU. Pazarlama kampanyalarınızın etkinliğini anlamak için bu değeri kurulum başına maliyetle (CPI) karşılaştırmak faydalıdır. | | ARPPU | ARPPU (Ödeme Yapan Kullanıcı Başına Ortalama Gelir), ödeme yapan kullanıcı başına ortalama gelirdir. Toplam gelirin benzersiz ödeme yapan kullanıcı sayısına bölünmesiyle hesaplanır. $60.000 gelir / 1.000 ödeme yapan kullanıcı = $60 ARPPU. Ödeme yapan bir müşterinin ortalama ne kadar gelir oluşturduğunu anlamanızı sağlar. | | ARPAS | ARPAS, aktif abone başına ortalama gelirdir. Toplam gelirin aktif abone sayısına bölünmesiyle hesaplanır. Abone olarak deneme süresi veya abonelik başlatanlar kastedilmektedir. $60.000 gelir / 1.500 abone = $40 ARPAS. | | Installs | Installs, uygulamayı ilk kez yükleyen kullanıcıların toplam sayısının yanı sıra mevcut kullanıcıların yeniden yüklemelerini de kapsar. Farklı cihazlarda aynı kullanıcı tarafından yapılan birden fazla yükleme de dahildir. Tamamlanmamış indirmeler veya tamamlanmadan iptal edilen yüklemeler kurulum sayısına dahil edilmez. | | Installs CR | Installs CR (Dönüşüm Oranı), toplam indirmeler içinde uygulamayı yükleyen kullanıcıların yüzdesidir. Formül: Total Downloads > 0 ise (Installs / Total Downloads) × 100%, aksi hâlde 0% | | CPI | CPI (Kurulum Başına Maliyet), Adapty tarafından kaydedilen kurulum başına maliyettir. Formül: Installs > 0 ise Spend / Installs, aksi hâlde 0 | | Trials | Trials, raporlama dönemi içinde başlatılan yeni deneme aboneliklerinin sayısıdır. | | Trial CR | Trial CR (Dönüşüm Oranı), toplam indirmelerin deneme başlatan yüzdesidir. Formül: Total Downloads > 0 ise (Trials / Total Downloads) × 100%, aksi hâlde 0% | | Cost per Trial | Cost per Trial, toplam harcamanızın yeni deneme başlatma sayısına bölünmesiyle hesaplanır. Formül: Trials > 0 ise Spend / Trials, aksi hâlde 0 | | Trials converted | Trials converted, raporlama dönemi içinde ücretli aboneliğe başarıyla dönüşen deneme aboneliklerinin sayısıdır. | | Trial converted CR | Trial converted CR (Dönüşüm Oranı), ücretli aboneliğe dönüşen deneme aboneliklerinin yüzdesidir. Formül: Trials > 0 ise (Trials converted / Trials) × 100%, aksi hâlde 0% | | Cost per Trial converted | Cost per Trial converted, toplam harcamanızın aynı dönemde dönüşen deneme sayısına bölünmesiyle hesaplanır. Formül: Trials converted > 0 ise Spend / Trials converted, aksi hâlde 0 | | Subscriptions | Subscriptions, raporlama dönemi içindeki toplam yeni abonelik kaydı (deneme dışı) sayısıdır. | | Subscription CR | Subscription CR (Dönüşüm Oranı), toplam indirmelerin ücretsiz deneme olmaksızın ücretli abonelik başlatan yüzdesidir. Formül: Total Downloads > 0 ise (Subscriptions / Total Downloads) × 100%, aksi hâlde 0% | | Cost per Subscription | Cost per Subscription, toplam harcamanızın başlatılan yeni abonelik sayısına bölünmesiyle hesaplanır. Formül: Subscriptions > 0 ise Spend / Subscriptions, aksi hâlde 0 | | Non-subscriptions started | Non-subscriptions started, abonelik tabanlı olmayan tek seferlik uygulama içi satın almaların toplam sayısıdır. | | Non-subscription CR | Non-subscription CR (Dönüşüm Oranı), toplam indirmelerin uygulamanızda abonelik dışı satın alma yapan yüzdesidir. Formül: Total Downloads > 0 ise (Non-subscriptions started / Total Downloads) × 100%, aksi hâlde 0% | | Cost per Non-subscription | Cost per Non-subscription, toplam harcamanızın abonelik dışı satın alma sayısına bölünmesiyle hesaplanır. Formül: Non-subscriptions started > 0 ise Spend / Non-subscriptions started, aksi hâlde 0 | ## Gelişmiş indirmeler \{#advanced-downloads\} | Metrik | Açıklama | |--------|----------| | New Downloads (Total) | Raporlama dönemi içinde tıklama yoluyla ve görüntüleme yoluyla gerçekleşen toplam yeni indirme sayısı. | | New Downloads (View-Through) | Reklamınızı görüntüleyen ancak tıklamayan ve daha önce uygulamanızı indirmemiş kullanıcıların 24 saatlik süre içindeki yeni indirmeleri. | | New Downloads (Tap-Through) | Reklamınıza tıklayan ve daha önce uygulamanızı indirmemiş kullanıcıların yeni indirmeleri. 30 günlük attribution penceresi içinde sayılır. | | New Download Share (Tap-Through) | Tıklamalardan gelen toplam indirmeler içindeki yeni indirmelerin yüzdesini gösterir (30 günlük attribution penceresi içinde reklamınıza tıklayan kullanıcılardan). | | Redownloads (Total) | Raporlama dönemi içinde tıklama yoluyla ve görüntüleme yoluyla gerçekleşen toplam yeniden indirme sayısı. | | Redownloads (View-Through) | Reklamı görüntüleyen ancak 24 saatlik süre içinde tıklamayan kullanıcıların yeniden indirmeleri. Bir kullanıcı uygulamayı indirip sildikten sonra aynı veya farklı bir cihazda reklamı görüntüleyerek tekrar indirdiğinde sayılır. | | Redownloads (Tap-Through) | 30 günlük attribution penceresi içinde reklamınıza tıklayan kullanıcıların yeniden indirmeleri. Bir kullanıcı uygulamayı indirip sildikten sonra aynı veya farklı bir cihazda reklamı tıklayarak tekrar indirdiğinde sayılır. | | Redownloads Share (Tap-Through) | Tıklamalardan gelen toplam indirmeler içindeki yeniden indirmelerin yüzdesini gösterir. | ## Öngörüler \{#insights\} | Metrik | Açıklama | |--------|----------| | Impression Share | Impression Share, reklamınızın aynı arama terimi için toplam gösterimlerle karşılaştırıldığında aldığı gösterim yüzdesidir. | | Rank | Rank (mevcut), belirli bir ülke veya bölgede seçilen arama terimi için uygulamanızın impression share açısından mevcut sıralamasıdır. | | Search Popularity | Search Popularity (mevcut), ülke veya bölgeye göre arama terimlerinin popülerliğidir. Sıralama 1-5 arasındadır; 5 en yüksek arama hacmini temsil eder. | --- # File: ads-manager-create-campaign --- --- title: "Adapty Ads Manager'da kampanyaları yönetme" description: "Adapty Ads Manager'da Apple Ads kampanyaları oluşturun ve düzenleyin." --- Adapty Ads Manager, Apple Ads ile iki yönlü entegrasyon sunar: neredeyse gerçek zamanlı performans verilerine ulaşabilir ve kampanyalarınızı doğrudan Adapty Kontrol Paneli üzerinden, native arayüze kıyasla çok daha kolay bir şekilde oluşturup düzenleyebilirsiniz. Apple Ads kontrol panelinde oluşturduğunuz bir kampanya, 24 saat içinde otomatik olarak Adapty Ads Manager'da görünecektir. [Kapsamlı kampanya metriklerini incelemenin](adapty-ads-manager-analytics) yanı sıra tüm kampanya ayarlarını yönetebilirsiniz: - Kampanya oluşturma - Mevcut kampanyaları düzenleme - Kampanyaları başlatma ve duraklatma :::tip Günlük bütçe sınırına ulaşan veya geri dönüşü olmayan kampanyalar gibi ilgilenilmesi gereken kampanyaları bulmak için [AI Agent](ads-manager-ai-agent)'a danışın. ::: ## Kampanya nedir? \{#what-is-a-campaign\} Bir kampanya tek bir uygulamaya odaklanır ve App Store'daki bir placement'ta reklam yayınlar. Her kampanya, uygulamanızı tanıtmaya yönelik belirli bir stratejiye odaklanan günlük bütçe ve [reklam grupları](ads-manager-create-ad-group) içerir. Kampanya, bütçe ayarlarına göre harcamaya devam eder. :::important Bir kampanyanın kendi başına çalışamayacağını unutmayın; varsayılan teklif, kitle ve anahtar kelimelerin belirleneceği yer reklam gruplarıdır. Bir reklam grubu olmadan kampanyanın hedefleme veya teklif mekanizması olmaz ve yayınlanmaz. Kampanyayı oluşturduktan sonra etkinleştirmek için [en az bir reklam grubu ekleyin](ads-manager-create-ad-group). ::: ## Kampanya oluşturma \{#create-campaigns\} Bir kampanya oluşturmak için: 1. **Ads Manager** sayfasını açın ve **+** simgesine tıklayın. Kampanya sihirbazını başlatmak için **Create campaign** seçeneğini seçin. 2. Reklamınız için bir **placement** seçin, ardından **Start** düğmesine tıklayın: | Placement | Reklamınızın görüneceği yer | | --- | --- | | **Search Results** | App Store arama sonuçlarının en üstünde. | | **Search Tab** | Kullanıcı aramadan önce, Arama sekmesindeki önerilen uygulamalar listesinde. | | **Today Tab** | App Store'un Today sayfasında. | | **Product Pages** | Diğer ürünlerin sayfalarındaki **You Might Also Like** listesinde. Apple, ilgili sayfaları sizin için seçer. | | **Duplicate a Campaign** | Mevcut bir kampanyadan placement, reklam grupları ve anahtar kelimeleri yeniden kullanın. | 3. **Arama Sonucu kampanyaları** için **kampanya türünü** seçin. Kampanyaları türe göre gruplandırmak, rapor verilerinizi düzenler ve Adapty'nin uygun bir anahtar kelime stratejisi önermesini sağlar. :::note Manuel anahtar kelime seçimini atlamak ve Apple'ın otomatik teklifinin dönüşümler için optimize etmesine izin vermek için **Max Conversions** seçeneğini belirleyin. ::: | Kampanya türü | Açıklama | | --- | --- | | **Generic** | Uygulamanızın ne yaptığını açıklayan markasız terimler. | | **Competitor** | Rakiplerinizin markalı anahtar kelimeleri. | | **Discovery** | Search Match, yeni anahtar kelimeleri otomatik olarak ortaya çıkarır; böylece kazananları toplayabilirsiniz. | | **Max Conversions** | Apple'ın dönüşümler için optimize edilmiş otomatik teklif sistemi. **Target CPA** değerini Ayarlar adımında belirleyin. | | **Brand** | Uygulamanızın markasıyla ilişkili anahtar kelimeler. | | **Custom** | Önceden tanımlanmış strateji yok. Kampanyayı sıfırdan oluşturun. | 4. **Uygulamayı** (tanıtmak istediğiniz uygulama) ve **kampanya grubunu** (kampanyayı yürüten ve ödemesini yapan Apple Ads hesabı) seçin. 5. Hedeflemek istediğiniz **ülke veya bölgeleri** seçin. Daha kolay optimizasyon için ülke başına bir kampanya kullanın. 6. Kampanyanın **temel ayarlarını** yapılandırın. Kitle hedefleme ve anahtar kelimeler, kampanyayı oluşturduktan sonra eklediğiniz kampanyanın [reklam gruplarında](ads-manager-create-ad-group) yer alır. | Ayar | Açıklama | | --- | --- | | **Campaign name** | Uygulama, placement ve ülkeden otomatik doldurulur. İstediğiniz zaman düzenleyebilirsiniz. | | **Daily budget** | Kampanyanın günlük harcayabileceği tutar. | | **Target CPA** | Otomatik teklif sistemi için edinim başına maliyet hedefi. Yalnızca Max Conversions kampanyalarında görünür. | | **Ad scheduling** | İsteğe bağlı. Daha sonraki bir başlangıç tarihi belirlemediğiniz sürece kampanya hemen başlar; belirli bir zamanda durdurmak için bitiş tarihi ekleyin. | Kredi hesapları da bu adımda faturalama ayrıntılarını doldurur. 7. Özeti inceleyin, ayrıntıları onaylayın ve **Create campaign** seçeneğine tıklayın. 8. [Reklam grubunu yapılandırmaya](ads-manager-create-ad-group) geçin. Kampanyalar reklam grubu olmadan çalışamaz — reklam grupları kitleyi ve/veya anahtar kelimeleri belirler. ## Kampanyaları düzenle \{#edit-campaigns\} Oluşturulmuş herhangi bir kampanyayı düzenlemek için: 1. Kampanya ayarlarını aşağıdaki yöntemlerden biriyle açın: - **Ads Manager > Campaigns** bölümünde kampanya adına tıklayın. Ardından sağ üst köşedeki **Edit campaign** seçeneğine tıklayın. - Ya da kampanya adının yanındaki onay kutusunu seçin ve **Actions > Edit campaign settings** seçeneğine tıklayın. 2. Kampanya ayarlarını düzenleyin. Kampanya adını, kampanya türünü (Arama Sonuçları kampanyaları için), ülkeleri ve günlük bütçeyi düzenleyebilirsiniz. Reklam yerleşimini, teklif stratejisini veya zamanlamayı değiştirmek için bunun yerine yeni bir kampanya oluşturun. 3. **Save changes** seçeneğine tıklayın. Ayrıca bir kampanyanın türünü, kampanyalar tablosundaki **Campaign type** sütununda doğrudan da değiştirebilirsiniz. :::note Apple Ads'te doğrudan yapılan düzenlemeler Adapty Ads Manager ile otomatik olarak senkronize edilir, ancak görünmesi zaman alabilir. ::: ## Kampanya dışa aktarma \{#export-campaigns\} Kampanya tablosunu CSV olarak dışa aktarmak için tablonun üzerindeki indirme simgesine tıklayın ve **Export current page** ya da **Export all pages** seçeneğini belirleyin. **Export all pages**, tüm sayfalardaki kampanyaları tek bir dosyaya indirir. Bir ilerleme penceresi indirmeyi takip eder; istediğiniz zaman iptal edebilirsiniz. İki isteğe bağlı filtre mevcuttur: - **Enabled only**: Yalnızca aktif kampanyaları dahil eder. - **With spend ≥**: Yalnızca belirtilen eşiğin üzerinde harcama yapan kampanyaları dahil eder. - **Group by country**: Her kampanya satırını ülkeye göre ayrıştırır. Tablo, kontrol panelinizde göründüğü haliyle, görüntülemeyi seçtiğiniz sütunlarla birlikte dışa aktarılır. ## Kampanyaları başlatma ve duraklatma \{#launch--pause-campaigns\} Adapty Ads Manager'dan herhangi bir kampanyayı başlatmak veya duraklatmak için: 1. **Ads Manager > Campaigns** bölümüne gidin. 2. **Status** sütunundaki kampanya adının yanındaki geçiş düğmesini açın veya kapatın. ## Kampanyaları silme \{#delete-campaigns\} Adapty Ads Manager kampanyaları silemez. Harcamayı durdurmak ancak ayarları ve analitik verileri korumak için kampanyayı silmek yerine [duraklatabilirsiniz](#launch-pause-campaigns). --- # File: ads-manager-create-ad-group --- --- title: "Adapty Ads Manager'da reklam gruplarını yönetme" description: "Adapty Ads Manager'da Apple Ads reklam grupları oluşturun ve düzenleyin." --- Adapty Ads Manager, Apple Ads ile çift yönlü entegrasyon sunar: neredeyse gerçek zamanlı performans verilerine erişir ve Adapty kontrol panelinden kampanyaları, native arayüze kıyasla çok daha kolay bir şekilde oluşturup düzenleyebilirsiniz. Apple Ads kontrol panelinde bir reklam grubu oluşturursanız, 24 saat içinde Adapty Ads Manager'da otomatik olarak görünür. [Kapsamlı kampanya metriklerini incelemenin](adapty-ads-manager-analytics) yanı sıra tüm reklam grubu ayarlarını yönetebilirsiniz: - Reklam grubu oluşturma - Mevcut reklam gruplarını düzenleme - Reklam gruplarını başlatma ve duraklatma ## Reklam grubu nedir \{#what-is-ad-group\} Reklam grubu, bir [kampanyaya](ads-manager-create-campaign) bağlıdır ve reklamlarınız için hedefleme ile teklif stratejisini yapılandırdığınız yerdir. Her reklam grubu; teklifler, kitle hedefleme ve reklamlarınızın ne zaman ve kime gösterileceğini belirleyen [anahtar kelimeler](ads-manager-manage-keywords) içerir. Reklam grupları, kampanya içindeki reklam stratejinizi düzenlemenize ve farklı hedefleme yaklaşımlarını test etmenize olanak tanır. :::important Bir kampanyanın reklam grupları olmadan yayına giremeyeceğini unutmayın. Varsayılan teklif, kitle ve anahtar kelimeler reklam grubu düzeyinde belirlenir; en az bir reklam grubu olmadan kampanyanın hedefleme veya teklifi bulunmaz ve reklamlar gösterilmez. Önce kampanyayı oluşturun, ardından etkinleştirmek için [en az bir reklam grubu ekleyin](ads-manager-create-ad-group). ::: ## Reklam grubu oluşturma \{#create-ad-groups\} Yeni bir Apple Ads reklam grubu oluşturmak için: 1. Kenar çubuğu menüsünden **Ads Manager**'a gidin. Herhangi bir sekmede, tablonun üzerindeki **+** simgesine tıklayın ve **Create ad group** seçeneğini seçin. 2. Reklam grubunu eklemek istediğiniz uygulamayı seçin. 3. Reklam grubunu eklemek istediğiniz kampanyayı seçin. 4. Reklam grubu ayarlarını yapılandırın: - **Ad group name**: Reklam grubunuzu kontrol panelinde tanımlamak ve aramak için atadığınız etiket. - **Default max CPT bid**: Reklamınıza yapılan bir dokunuş için ödemeye razı olduğunuz maksimum tutar. Bu teklif, bireysel anahtar kelime teklifleri ayarlamadığınız sürece reklam grubundaki tüm anahtar kelimeler için geçerlidir. - **CPA cap (limits impressions)** (İsteğe bağlı): Dokunma yoluyla gerçekleşen dönüşüm başına (örneğin indirme veya başka bir hedef eylem) harcamaya razı olduğunuz maksimum tutarı belirtir. Reklam grubunuzdaki tüm anahtar kelimeler için bir teklif tavanı belirler. Teklif tavanı, girdiğiniz CPA cap değerinin dokunma yoluyla dönüşüm oranınızla çarpılmasıyla hesaplanır: `CPA Cap × CR (Tap-Through)`. Anahtar kelime maksimum CPT teklifi bu değerden düşükse, daha düşük olan maksimum CPT teklifi uygulanır. Örneğin CPA cap'iniz 5$ ve dokunma yoluyla dönüşüm oranınız %65 ise, reklam grubundaki tüm anahtar kelimeler için uygulanan maksimum teklif 3,25$ olur. Maksimum CPT 4$ olarak ayarlandıysa, uygulanan maksimum teklif yine de 3,25$ olur. - **Search Match**: Anahtar kelime belirtmeden reklamınızı ilgili aramalara otomatik olarak eşleştirmek için bu seçeneği açın. Etkinleştirildiğinde Apple Ads, reklamınızı uygulamanızın meta verilerine ve kategorisine ilişkin aramalarda gösterebilir. - **Audience**: Reklamlarınızı kimin göreceğini belirleyen hedefleme kriterleri. - **All eligible users**: Reklamlarınızı kampanyanıza uygun tüm kullanıcılara gösterir. - **Specific audiences**: Belirli kullanıcı segmentlerini hedeflemek için şunları yapılandırın: - **Devices**: iPad, iPhone veya her ikisini hedefleyin. - **Customer type**: Tüm kullanıcıları, yeni kullanıcıları veya geri dönen kullanıcıları hedefleyin. - **Gender**: Cinsiyete göre veya tüm kullanıcıları hedefleyin. - **Age range**: Belirli yaş aralıklarını veya tüm kullanıcıları hedefleyin. - **Ad scheduling** (İsteğe bağlı, **Specific audiences** seçildiğinde kullanılabilir): Reklamlarınızın ne zaman yayınlanmaya başlayacağını ayarlayın: - **Start date and time**: Reklam grubunun reklam yayınlamaya ne zaman başlaması gerektiği. - **End date** (İsteğe bağlı): Reklam grubunun reklam yayınlamayı ne zaman durdurması gerektiği. 5. **Create** düğmesine tıklayın. 6. Kampanya placement türünüz **Search results** ise reklam yayınlamaya başlamak için şimdi [anahtar kelime ekleyebilirsiniz](ads-manager-manage-keywords). Diğer placement türleri için her şey hazır. :::note **Max Conversions** kampanyasında reklam grubunun bir **Bidding strategy** geçiş düğmesi bulunur: **Standard** veya **Automated**. **Default max CPT bid** alanı yoktur. **Automated** seçeneğiyle bir hedef CPA belirlersiniz ve Apple teklifleri sizin için optimize eder. ::: ## Reklam gruplarını düzenleme \{#edit-ad-groups\} Oluşturulmuş bir reklam grubunu düzenlemek için: 1. Kampanya ayarlarını şu yöntemlerden biriyle açın: - **Ads Manager > Ad groups** bölümünde kampanya adına tıklayın. Ardından sağ üst köşedeki **Edit ad group** seçeneğine tıklayın. - Ya da reklam grubu adının yanındaki onay kutusunu seçin ve **Actions > Edit ad group settings** seçeneğine tıklayın. 2. Reklam grubu ayarlarını düzenleyin. Uygulama, kampanya, kitle türü ile başlangıç tarihi ve saati değiştirilemez. Otomatik reklam grubunda yalnızca ad düzenlenebilir. 3. **Save changes** seçeneğine tıklayın. Bir reklam grubunu kopyalamak için **Ads Manager > Ad groups** bölümünde ilgili grubu seçin ve **Actions > Duplicate ad group** seçeneğine tıklayın. :::note Apple Ads'te bir reklam grubunda yapılan düzenlemeler otomatik olarak Adapty Ads Manager ile senkronize edilir, ancak Adapty Ads Manager'da görünmesi biraz zaman alabilir. ::: ## Reklam gruplarını dışa aktarma \{#export-ad-groups\} Reklam grupları tablosunu CSV olarak dışa aktarmak için tablonun üzerindeki indirme simgesine tıklayın ve **Export current page** ya da **Export all pages** seçeneğini seçin. **Export all pages**, tüm sayfalardaki reklam gruplarını tek bir dosyaya indirir. Bir ilerleme penceresi indirmeyi takip eder; istediğiniz zaman iptal edebilirsiniz. İki isteğe bağlı filtre mevcuttur: - **Enabled only**: Yalnızca etkin reklam gruplarını dahil edin. - **With spend ≥**: Yalnızca belirtilen eşiğin üzerinde harcaması olan reklam gruplarını dahil edin. - **Group by country**: Her reklam grubu satırını ülkeye göre ayırın. Tablo, görüntülemek üzere seçtiğiniz sütunlarla kontrol panelinizde göründüğü şekilde dışa aktarılır. ## Reklam gruplarını başlatma ve duraklatma \{#launch--pause-ad-groups\} Adapty Ads Manager'dan herhangi bir reklam grubunu başlatmak veya duraklatmak için: 1. **Ads Manager > Ad groups** bölümüne gidin ya da reklam gruplarını görmek için bir kampanya sayfasına gidin. 2. **Status** sütununda reklam grubu adının yanındaki geçiş düğmesini açın veya kapatın. --- # File: ads-manager-manage-keywords --- --- title: "Adapty Ads Manager'da anahtar kelimeleri yönetin" description: "Adapty Ads Manager'da Apple Ads anahtar kelimelerini, negatif anahtar kelimeleri ve SKAG anahtar kelimelerini ekleyin ve yönetin." --- Adapty Ads Manager, Apple Ads ile çift yönlü entegrasyona sahiptir: neredeyse gerçek zamanlı performans verilerine ulaşabilir ve anahtar kelimeleri doğrudan Adapty kontrol panelinden, yerel arayüze kıyasla çok daha kolay bir şekilde oluşturup düzenleyebilirsiniz. Apple Ads kontrol panelinde bir anahtar kelime oluşturursanız, bu anahtar kelime 24 saat içinde otomatik olarak Adapty Ads Manager'da görünür. [Kapsamlı analizleri incelemenin](adapty-ads-manager-analytics) yanı sıra tüm anahtar kelime ayarlarınızı yönetebilirsiniz: - Reklam gruplarına anahtar kelime ekleme - Negatif anahtar kelime ekleme - Anahtar kelimeleri SKAG (Tek Anahtar Kelimeli Reklam Grubu) olarak ekleme - Anahtar kelimeleri doğrudan tabloda düzenleme - Birden fazla anahtar kelime üzerinde toplu işlem yapma - Anahtar kelimeleri başlatma ve duraklatma :::tip Hesabınızdaki düşük performanslı anahtar kelimeleri bulmak için — örneğin harcama olan ancak dönüşüm olmayan anahtar kelimeler — [AI Ajan](ads-manager-ai-agent)'a sorun. ::: ## Anahtar kelimeler nedir \{#what-are-keywords\} Anahtar kelimeler, reklamlarınızın App Store arama sonuçlarında görünmesini sağlayan arama terimleridir. Bu anahtar kelimeler, [kampanyalara](ads-manager-create-campaign) bağlı [reklam grupları](ads-manager-create-ad-group) içinde düzenlenir. Bu hiyerarşik yapı, reklam stratejinizi etkili biçimde organize etmenizi ve yönetmenizi sağlar. :::important Anahtar kelimeler yalnızca **Search results** yerleşim türüne sahip kampanyalarda geçerlidir. Diğer yerleşim türlerine sahip kampanyalarda (Search tab veya Product pages) anahtar kelimeler kullanılmaz. ::: ### Standart anahtar kelimeler \{#standard-keywords\} Standart anahtar kelimeler, reklamlarınızı tetiklemek için teklif verdiğiniz birincil terimlerdir. Kullanıcılar App Store'da bu terimleri aradığında reklamınız arama sonuçlarında görünebilir. ### Negatif anahtar kelimeler \{#negative-keywords\} Negatif anahtar kelimeler, uygulamanızla ilgisiz aramalarda reklamınızın görünmesini engeller. Negatif anahtar kelimeler ekleyerek alakasız aramalara yapılan gereksiz harcamaları azaltabilirsiniz. Negatif anahtar kelimeler reklam grubu düzeyinde ya da aynı anda birden fazla kampanyaya uygulanan çapraz grup negatif anahtar kelimeler olarak eklenebilir. ### SKAG olarak anahtar kelimeler (Tekli Anahtar Kelime Reklam Grubu) \{#keywords-as-skag-single-keyword-ad-group\} SKAG (Single Keyword Ad Group), tek bir anahtar kelime içeren ayrı reklam grupları oluşturduğunuz bir stratejidir. Bu yaklaşım şunları yapmanıza olanak tanır: - Yüksek değerli anahtar kelimeler için teklifler üzerinde hassas kontrol sağlama - Anahtar kelime düzeyinde performansı daha iyi analiz etme SKAG, özellikle en iyi performans gösteren anahtar kelimeleri belirlemek ve özel reklam gruplarıyla potansiyellerini en üst düzeye çıkarmak için kullanışlıdır. ## Anahtar kelime ekleme \{#add-keywords\} Bir reklam grubuna anahtar kelime eklemek için: :::note **Maximize Conversions** kampanyalarındaki anahtar kelimeler teklif kullanmaz — teklif verme, kampanyanın CPA hedefi tarafından otomatik olarak yönetilir. **CPT bid** alanı bu kampanyalar için geçerli değildir. ::: 1. Kenar çubuğu menüsünden **Ads Manager**'a gidin. Herhangi bir sekmede tablonun üzerindeki **+** simgesine tıklayın, ardından açılır menüden **Add keywords**'ü seçin. 2. Açılan pencerede, anahtar kelime eklemek istediğiniz kampanyaları ve reklam gruplarını seçin. Bir kampanyada reklam gruplarını seçtikten sonra başka bir kampanya seçerek listeye daha fazla reklam grubu ekleyebilirsiniz. 3. Devam etmek için **Select** düğmesine tıklayın. 4. **Add keywords** iletişim kutusunda, **Keywords list** alanına anahtar kelimeleri girin. Virgülle ayrılmış bir anahtar kelime dosyanız varsa, Adapty Ads Manager'ın tüm anahtar kelimeleri toplu olarak yüklemesi için içeriğini buraya yapıştırabilirsiniz. 5. Tablodaki her anahtar kelime için şunları yapılandırın: - **Match type**: **Exact** (tam) veya **Broad** (geniş) eşleşme türünü seçin - **CPT bid**: Bu anahtar kelime için maksimum tıklama başı teklifi belirleyin ya da reklam grubunun varsayılan maksimum CPT teklifini kullanmak için boş bırakın 6. Anahtar kelimelerinizi gözden geçirin ve **Add X keywords** düğmesine tıklayın (X, eklediğiniz anahtar kelime sayısını belirtir). :::important Bir anahtar kelimeyi kaydettikten sonra, eşleşme türü değiştirilemez. Eşleşme türünü değiştirmeniz gerekiyorsa, anahtar kelimeyi silin ve istediğiniz eşleşme türüyle tekrar ekleyin. ::: ## Negatif anahtar kelime ekleme \{#add-negative-keywords\} Negatif anahtar kelime eklemek için: 1. Kenar çubuğu menüsünden **Ads Manager**'a gidin. Herhangi bir sekmede, tablonun üzerindeki **+** simgesine tıklayın ve açılır menüden **Add negative keywords**'ü seçin. 2. **Add negative keywords to** modalında, negatif anahtar kelimeleri hangi düzeyde eklemek istediğinizi seçin: - **Selected campaigns**: Kampanya düzeyinde negatif anahtar kelimeler ekleyin. - **Selected ad groups**: Reklam grubu düzeyinde negatif anahtar kelimeler ekleyin. - **All ad groups in selected campaigns**: Seçilen kampanyalardaki tüm reklam gruplarına reklam grubu düzeyinde negatif anahtar kelimeler ekleyin. :::note Şunlara dikkat edin: - Reklam grubu düzeyindeki negatif anahtar kelimeler, kampanya düzeyindeki negatif anahtar kelimelerden daha yüksek önceliğe sahiptir. - Seçilen kampanyalardaki tüm reklam gruplarına negatif anahtar kelimeler eklerseniz, bu kampanyalara sonradan yeni reklam grupları eklemeye karar verdiğinizde bunları manuel olarak eklemeniz gerekir. ::: 3. **Keywords list** alanına negatif anahtar kelimeleri girin. Virgülle ayrılmış anahtar kelimeler içeren bir dosyanız varsa içeriğini yapıştırabilirsiniz; böylece Adapty Ads Manager tüm anahtar kelimeleri toplu olarak yükler. 4. Tablodaki her anahtar kelime için **Match type** seçin: - **Exact**: Yalnızca tam anahtar kelimeyi veya çok yakın varyasyonları hariç tutar. - **Broad**: Anahtar kelimeyi ve ilgili arama terimlerini hariç tutar. Ya da yanlarındaki onay kutularını seçerek eşleşme türünü toplu olarak değiştirebilirsiniz. 5. Negatif anahtar kelimelerinizi inceleyin ve **Add X keywords** düğmesine tıklayın (X, eklediğiniz anahtar kelime sayısıdır). :::note Gruplar arası negatif anahtar kelimeler, belirli arama terimlerini birden fazla kampanyada aynı anda hariç tutmak istediğinizde özellikle kullanışlıdır; bu sayede zaman kazanır ve reklam stratejiniz genelinde tutarlılığı sağlarsınız. ::: ## Anahtar Kelimeleri SKAG Olarak Ekleme \{#add-keywords-as-skag\} Anahtar kelimeleri SKAG (Tek Anahtar Kelime Reklam Grubu) olarak eklemek için: 1. Kenar çubuğu menüsünden **Ads Manager**'a gidin. Herhangi bir sekmede tablonun üzerindeki **+** simgesine tıklayın, ardından açılır menüden **Add keywords as SKAG** seçeneğini belirleyin. 2. SKAG reklam grupları oluşturmak istediğiniz kampanyaları seçin. Birden fazla kampanya seçebilirsiniz. 3. Varsayılan olarak, yeni reklam grupları tüm kullanıcıları hedefleyen varsayılan ayarlarla oluşturulur. Bunu değiştirmek istiyorsanız **Copy settings from ad group** seçeneğini belirleyin ve ayarları kopyalamak istediğiniz mevcut bir reklam grubu seçin. 4. Yeni reklam grupları için ayarları yapılandırın: - **Ad group name prefix**: Her reklam grubu adına eklenecek isteğe bağlı önek (ör. "SKAG_" ile "SKAG_keyword1", "SKAG_keyword2" vb. oluşturulur). Grup adlarına anahtar kelimeyi, kampanya adını ve ülkeyi dinamik olarak eklemek için **Tag** seçeneğine tıklayabilirsiniz. - **CPT bid** ve **CPA cap**: Tüm anahtar kelimeler için tek seferde teklif belirleyin ya da **Set CPT bid and CPA cap for each word manually** seçeneğini belirleyerek her anahtar kelime için ayrı ayrı teklif girin. 5. **Keywords list** alanına anahtar kelimeleri girin. Virgülle ayrılmış bir anahtar kelime dosyanız varsa, içeriğini yapıştırabilirsiniz; böylece Adapty Ads Manager tüm anahtar kelimeleri toplu olarak yükler. 6. Tablodaki her anahtar kelime için **Match type** seçin: - **Exact**: Yalnızca tam anahtar kelimeyle veya çok yakın varyasyonlarla eşleşir - **Broad**: Anahtar kelimeyle ve ilgili arama terimleriyle eşleşir Ya da yanlarındaki onay kutularını işaretleyip eşleşme türünü toplu olarak değiştirin. 7. Hedef kampanyalarda aynı anahtar kelimelerin bulunmadığından emin olmak için **Check for duplicates in target campaign** seçeneğini belirleyin. 8. SKAG reklam gruplarını oluşturmak için **Create**'e tıklayın. Her anahtar kelime, seçilen her kampanya içinde kendi reklam grubuna yerleştirilecek; böylece bunları bağımsız olarak yönetip optimize edebilirsiniz. ## Anahtar kelimeleri düzenle \{#edit-keywords\} Mevcut anahtar kelimeleri düzenlemek için: 1. **Ads Manager > Keywords** veya **Ads Manager > Negative keywords** bölümüne gidin ve tabloda düzenlemek istediğiniz anahtar kelimeyi bulun; ya da bir kampanya sayfasına, ardından bir reklam grubu sayfasına giderek anahtar kelimeyi bulun. 2. Değerleri doğrudan tabloda düzenleyin: - **CPT bid**: Teklif değerine tıklayın ve yeni bir maksimum tıklama başına maliyet teklifi girin - **Status**: Anahtar kelimeyi duraklatmak veya etkinleştirmek için geçiş düğmesini kullanın :::note Apple Ads üzerinde doğrudan anahtar kelimelere yapılan düzenlemeler otomatik olarak Adapty Ads Manager ile senkronize edilir; ancak Adapty Ads Manager'da görünmesi biraz zaman alabilir. ::: ## Toplu işlemler \{#bulk-actions\} Birden fazla anahtar kelime üzerinde toplu işlemler gerçekleştirerek zamandan tasarruf edebilir ve anahtar kelimelerinizi daha verimli yönetebilirsiniz. Toplu işlem gerçekleştirmek için: 1. **Ads Manager > Keywords** veya **Ads Manager > Negative keywords** sekmesine gidin. 2. Yönetmek istediğiniz anahtar kelimelerin yanındaki kutucukları işaretleyerek birden fazla anahtar kelime seçin. 3. **Actions** açılır menüsüne tıklayın ve aşağıdaki seçeneklerden birini belirleyin: - **Add as keywords**: Seçilen anahtar kelimeleri standart anahtar kelime olarak ekleyin - **Add as negative keywords**: Seçilen anahtar kelimeleri negatif anahtar kelime olarak ekleyin - **Add as SKAG**: Seçilen anahtar kelimeler için Tek Anahtar Kelimeli Reklam Grupları oluşturun - **Activate**: Seçilen anahtar kelimeleri etkinleştirin - **Pause**: Seçilen anahtar kelimeleri duraklatın - **Create segment from keywords**: Seçilen anahtar kelimelerden bir kitle segmenti oluşturun - **Copy keywords**: Seçilen anahtar kelime adlarını panonuza kopyalayın - **Edit CPT bids**: Seçilen anahtar kelimelerin CPT tekliflerini düzenleyin. Teklifleri farklı yöntemlerle düzenleyebilirsiniz: - **Set to**: Birden fazla teklifi belirli bir tutara ayarlayın. - **Increase by/decrease by**: Teklifleri belirli bir USD tutarı veya teklif yüzdesi kadar artırın ya da azaltın. İsteğe bağlı olarak, yanlışlıkla fazla harcama yapmamak için üst teklif sınırı belirleyin. - **Set to average CPT**: Teklifi CPT (tıklama başı maliyet) metriğine göre hizalamak için bu metriği kullanın. Bir çarpan katsayısı belirleyin. Örneğin, performans beklentilerin altındaysa çarpanı 0,9'a, beklentilerin üzerindeyse 1,1'e ayarlayın. - **Set to average CPA**: Teklifi CPA (edinim başı maliyet) metriğine göre hizalamak için bu metriği kullanın. Bir çarpan katsayısı belirleyin. **Negatif anahtar kelimeler** sekmesi sınırlı sayıda işlem içerir: - **Anahtar kelime olarak ekle** - **Negatif anahtar kelime olarak ekle** - **SKAG olarak ekle** - **Anahtar kelimeleri sil** seçenekleri kullanılabilir. :::tip Toplu işlemler özellikle şunlar için kullanışlıdır: - Anahtar kelimeleri farklı türler arasında dönüştürme (standart, negatif, SKAG) - Birden fazla anahtar kelime için diğer eşleşme türleriyle hızlıca anahtar kelime ekleme - En iyi performans gösteren anahtar kelimeleri filtreleme ve tekliflerini ayarlama - Düşük performanslı anahtar kelimeleri belirleme ve duraklatma ::: ## Anahtar kelimeleri dışa aktar \{#export-keywords\} Anahtar kelimeler tablosunu CSV olarak dışa aktarmak için tablonun üzerindeki indirme simgesine tıklayın ve **Export current page** ya da **Export all pages** seçeneğini belirleyin. **Export all pages**, tüm sayfalardaki anahtar kelimeleri tek bir dosyaya indirir. Bir ilerleme modalı indirmeyi takip eder; istediğiniz zaman iptal edebilirsiniz. İki isteğe bağlı filtre mevcuttur: - **Enabled only**: Yalnızca aktif anahtar kelimeleri dahil eder. - **With spend ≥**: Yalnızca belirtilen eşiğin üzerinde harcaması olan anahtar kelimeleri dahil eder. - **Group by country**: Her anahtar kelime satırını ülkeye göre ayrıştırır. Tablo, kontrol panelinde görüntülediğiniz şekilde, seçtiğiniz sütunlarla dışa aktarılır. ## Anahtar kelime düzeyindeki grafikleri keşfedin \{#explore-keyword-level-charts\} Herhangi bir anahtar kelime için grafiği doğrudan **Ads Manager > Keywords** tablosundan açabilirsiniz. Bu sayede her bir anahtar kelime için gün gün hassas performans analizi yapabilirsiniz. Grafiği görüntülemek için tablodaki anahtar kelimenin yanındaki grafik simgesine tıklayın. Grafik varsayılan olarak seçili anahtar kelime için **Spend** metriğini gösterir. Korelasyonları ve zaman içindeki değişimleri fark etmek için aynı anda birden fazla metrik görüntüleyebilirsiniz. Yeni bir metrik eklemek için **+** simgesine tıklayın. Yeniden başlamak için **Reset**'e tıklayın ya da metrikleri gizlemek için ilgili onay kutularının işaretini kaldırın. ## Teklif geçmişi \{#bid-history\} Bir anahtar kelime için teklif geçmişini görüntülemek amacıyla tablodaki **grafik simgesine** tıklayın. Açılan panelde iki sekme bulunur: **Metrics** ve **Bid History**. - **Metrics** sekmesi, zaman içindeki metrikleri gösteren bir grafik sunar. Metrikleri keyword düzeyindeki grafiklerle aynı şekilde ekleyip kaldırabilirsiniz — eklemek için **+** butonuna tıklayın, gizlemek için ilgili onay kutusunun işaretini kaldırın. Teklifin değiştirildiği her noktada bir işaret belirir — o tarihteki tam teklif miktarını görmek için işaretin üzerine gelin. Bunu teklif değişiklikleriyle performans dalgalanmalarını ilişkilendirmek için kullanın: bir değişiklikten sonra metrik düşmüş ya da yükselmişse işaret tam olarak ne zaman gerçekleştiğini gösterir. - **Bid History** sekmesi, her teklif değişikliğini listeler: tarihi, türü, önceki ve yeni değerleri ile neyin tetiklediğini — manuel bir değişiklik mi yoksa bir otomasyon kuralı mı (kuralın kimliğiyle birlikte gösterilir). --- # File: ads-manager-manage-ads --- --- title: "Adapty Ads Manager'da reklamları yönetin" description: "Adapty Ads Manager'da Apple Ads reklamları oluşturun ve düzenleyin." --- Adapty Ads Manager, Apple Ads ile çift yönlü entegrasyon sunar: neredeyse gerçek zamanlı performans verilerine ulaşabilir, yerel arayüze kıyasla çok daha kullanışlı bir şekilde reklamları doğrudan Adapty kontrol panelinden oluşturup düzenleyebilirsiniz. Apple'ın yerel reklam kontrol panelinde bir reklam oluşturursanız, 24 saat içinde Adapty Ads Manager'da otomatik olarak görünür. ## Reklamlar nedir \{#what-are-ads\} Reklam, bir [kampanya](ads-manager-create-campaign) içindeki bir [reklam grubuna](ads-manager-create-ad-group) atanan reklam görseli öğesidir. Reklam grubu başına yalnızca bir aktif reklam atayabilirsiniz. ## Reklam oluşturma \{#create-ads\} Başlamadan önce aşağıdakileri oluşturduğunuzdan emin olun: - **Reklam grubu**. [Bunu doğrudan Adapty Ads Manager kontrol panelinde oluşturabilirsiniz](ads-manager-create-ad-group). - **Özel ürün sayfası**. Bunu [doğrudan Apple Ads üzerinde ayarlamanız](https://developer.apple.com/help/app-store-connect/create-custom-product-pages/configure-multiple-product-page-versions/) gerekir. Reklamınızda kullanabilmek için önce App Store tarafından onaylanmış olması gerekir. :::note Seçili reklam grubunda zaten aktif bir reklam varsa, yeni reklamı yayınlamak için bu reklam duraklatılacaktır. ::: Yeni bir Apple Ads reklamı oluşturmak için: 1. Kenar çubuğu menüsünden **Ads Manager** bölümüne gidin. Herhangi bir sekmede, tablonun üzerindeki **+** simgesine tıklayın ve **Create ad** seçeneğini seçin. 2. Reklamı yayınlamak istediğiniz uygulamayı seçin. 3. Bir veya daha fazla reklam grubu seçin. Adapty, reklamı seçilen her reklam grubunda oluşturur. 4. Reklam adını girin. 5. Reklam durumunu ayarlayın. Reklamı daha sonra yayınlamak için **Status** geçişini kapatın. 6. **Select CPP** seçeneğine tıklayın. App Store tarafından onaylanmış uygulamanıza ait tüm özel ürün sayfalarını göreceksiniz. Yalnızca bir özel ürün sayfası seçebilirsiniz. 7. **Create ad**'e tıklayın. ## Reklamları düzenle \{#edit-ads\} :::note Bir reklam oluşturduktan sonra adını ve durumunu düzenleyebilirsiniz. CPP'sini değiştiremez veya farklı bir reklam grubuna taşıyamazsınız. ::: Reklam adını düzenlemek için aşağıdaki seçeneklerden birini kullanın: - **Ads Manager > Ads** bölümünde reklam adına tıklayın. Reklam adını düzenleyip yanındaki onay işaretine tıklayın. - Reklam adının yanındaki onay kutusunu işaretleyin ve **Actions > Edit ad** seçeneğine tıklayın. Reklam adını veya durumunu değiştirip **Save changes** seçeneğine tıklayın. :::note Apple Ads üzerinde doğrudan bir reklamda yapılan düzenlemeler otomatik olarak Adapty Ads Manager ile senkronize edilir, ancak Adapty Ads Manager'da görünmesi biraz zaman alabilir. ::: ## Reklamları dışa aktarma \{#export-ads\} Reklam tablosunu CSV olarak dışa aktarmak için tablonun üzerindeki indirme simgesine tıklayın ve **Export current page** ya da **Export all pages** seçeneğini belirleyin. **Export all pages**, tüm sayfalardaki reklamları tek bir dosyaya indirir. Bir ilerleme modalı indirmeyi takip eder; istediğiniz zaman iptal edebilirsiniz. İki isteğe bağlı filtre mevcuttur: - **Enabled only**: Yalnızca aktif reklamları dahil eder. - **With spend ≥**: Yalnızca belirtilen eşiğin üzerinde harcaması olan reklamları dahil eder. - **Group by country**: Her reklam satırını ülkeye göre ayrıştırır. Tablo, kontrol panelinde göründüğü şekliyle, görüntülemek için seçtiğiniz sütunlarla birlikte dışa aktarılır. ## Reklamları başlatma ve duraklatma \{#launch--pause-ads\} Adapty Ads Manager'dan herhangi bir reklamı başlatmak veya duraklatmak için aşağıdaki seçeneklerden birini kullanın: - **Ads Manager > Ads** bölümünde **Status** geçiş düğmesini açın veya kapatın. - Reklam adının yanındaki onay kutusunu seçin, **Actions > Edit ad** seçeneğine tıklayın, **Status** geçiş düğmesini değiştirin ve **Save changes** seçeneğine tıklayın. --- # File: ads-manager-create-segments --- --- title: "Adapty Ads Manager'da Apple Ads attribution'ına dayalı segmentler oluşturma" description: "Adapty Ads Manager'da kampanyalardan, reklam gruplarından ve anahtar kelimelerden iki tıklamayla segmentler oluşturun." --- [Adapty Ads Manager](adapty-ads-manager)'dan kampanyaları, reklam gruplarını veya anahtar kelimeleri seçerek birkaç tıklamayla [segment](segments) oluşturabilirsiniz. Bu sayede segment koşullarını elle ayarlamadan, edinim kaynağına göre paywallları ve teklifleri kolayca kişiselleştirebilirsiniz. Bir segment oluşturduktan sonra farklı ürünler ve fiyatlar atamak, A/B testleri çalıştırmak ve paywall görünümünü özelleştirmek için kullanabilirsiniz. ## Kullanım senaryoları \{#use-cases\} Apple Ads verilerinden oluşturulan segmentlerin pratikte nasıl kullanılabileceğine dair bazı örnekler: - **Anahtar kelime tabanlı paywalllar**. Yüksek niyetli anahtar kelimelerden gelen kullanıcılara özellik odaklı bir paywall, daha geniş keşif anahtar kelimelerinden gelen kullanıcılara ise genel bir paywall gösterin. - **Kampanya düzeyinde teklifler**. Seçili Apple Ads kampanyalarından gelen kullanıcılara daha uzun deneme süreleri veya özel fiyatlandırma sunarken diğer kullanıcılar için standart teklifi koruyun. - **Reklam kreatifinden paywalla tutarlılık**. Belirli özellikleri tanıtan reklam gruplarından gelen kullanıcıları, önce o özellikleri öne çıkaran paywallara yönlendirin. - **Yüksek ROI'li kampanya optimizasyonu**. Sürekli olarak daha yüksek yaşam boyu değer sağlayan kampanyalardan gelen kullanıcılara premium öncelikli, tam fiyatlı paywall gösterin. ## Segment oluşturma \{#create-segments\} Adapty Ads Manager'dan segment oluşturmak için: 1. **Ads Manager**'a gidin ve **Campaigns**, **Ad groups** ya da **Keywords** sekmesine geçin. Kullanmak istediğiniz öğelerin yanındaki onay kutularını seçin. Birden fazla öğe seçerseniz, her öğe için ayrı bir segment değil, hepsini kapsayan tek bir segment oluşturulacağını unutmayın. 2. **Actions > Create segment from campaigns/ad groups/keywords** seçeneğine tıklayın. 3. Gerekirse, **Create segment** penceresindeki segment ayrıntılarını güncelleyin: - **Adapty project**: Bu segmenti oluşturmak istediğiniz Adapty uygulaması. - **Build segment from campaign/ad group**: Kampanyalardan veya reklam gruplarından segment oluştururken, bu adımda seçili kampanyaları veya reklam gruplarını ayarlayabilirsiniz. - **Segment name** - **Segment description** 4. **Create** düğmesine tıklayın. 5. Segmentiniz oluşturulduktan sonra onu kullanmaya hazırlanabilirsiniz: - Mevcut bir paywall veya onboarding ile kullanmak için bir [placement](placements)'a ekleyin - Segmentteki kullanıcılara gösterilecek yeni bir [paywall](adapty-paywall-builder) veya [onboarding](onboardings) tasarlayın - Bir [A/B testi](ab-tests) çalıştırın --- # File: ads-manager-automations-keyword-rules --- --- title: "Adapty Ads Manager'da anahtar kelime kuralları" description: "Kampanya performansına göre teklifleri ayarlayarak, anahtar kelimeleri etkinleştirerek veya duraklatarak ve bunları reklam grupları arasında taşıyarak anahtar kelime yaşam döngüsünü otomatik olarak yönetin." --- Anahtar kelime kuralları, kurulum aşamasından deneme, abonelik ve gelire uzanan tüm hunideki performansa göre anahtar kelimeleriniz üzerinde otomatik işlem yapar. Harcama, CPA, ROAS ve kohort verileri gibi metrikleri kullanarak koşullar tanımlayın, ardından bu koşullar karşılandığında kuralın ne yapacağını seçin. Kurallar, belirlediğiniz bir zamanlamaya göre çalışır. Manuel müdahale gerektirmeden performans değişikliklerine yanıt verir. ## Kullanılabilir işlemler \{#available-actions\} Her anahtar kelime kuralı, koşulları karşılandığında tek bir işlem gerçekleştirir: | İşlem | Ne yapar | |--------|-------------| | **Teklifi değiştir** | CPT teklifini artırır, azaltır veya belirli bir değere ayarlar | | **Anahtar kelimeyi etkinleştir** | Duraklatılmış bir anahtar kelimeyi yeniden etkinleştirir | | **Anahtar kelimeyi duraklat** | Aktif bir anahtar kelimeyi duraklatır | | **Şuraya anahtar kelime olarak ekle…** | Anahtar kelimeyi belirtilen teklif ve eşleşme türüyle başka bir reklam grubuna kopyalar | | **Şuraya negatif anahtar kelime olarak ekle…** | Anahtar kelimeyi belirtilen reklam gruplarına veya kampanyalara negatif olarak ekler | ## Anahtar kelime kuralı oluşturma \{#create-a-keyword-rule\} Anahtar kelime kurallarını şablonlardan veya sıfırdan manuel olarak oluşturabilirsiniz. ### Şablondan \{#from-a-template\} Adapty, yaygın optimizasyon senaryoları için kullanıma hazır şablonlar sunar. Sık kullanılan şablonlar şunlardır: - **Dönüşüm sağlamayan anahtar kelimelerdeki israfı kes**: Harcama > X ve Kurulum veya Deneme = 0 olan yerlerde teklifleri düşür. - **Kazanan anahtar kelimeleri ölçeklendir**: ROAS > hedef veya CPA < hedef olan yerlerde teklifleri artır. Şablondan kural oluşturmak için: 1. Sol kenar çubuğunda **Automations** bölümüne gidin ve **Templates**'e tıklayın. 2. Bir şablon seçin ve **Next**'e tıklayın. 3. Önceden doldurulmuş ayarları gözden geçirip düzenleyin: - **Rule name**: Otomatik olarak şablon adı ve güncel tarihle ayarlanır (örneğin, "Scale Winning Keywords - [2025-11-12]"). - **Apply to**: Kuralın geçerli olacağı kampanya gruplarını, uygulamaları, kampanyaları veya reklam gruplarını seçin. - **Conditions**: Gerekirse önceden yapılandırılmış koşulları değiştirin. - **Action**: Gerekirse önceden ayarlanmış işlemi değiştirin. - **Schedule**: Kuralın ne sıklıkla çalışacağını ayarlayın. 4. Kuralı etkinleştirmek için **Save**'e tıklayın. ### Manuel olarak \{#manually\} Sıfırdan özel bir anahtar kelime kuralı oluşturmak için: 1. Sol kenar çubuğunda **Automations** bölümüne gidin, **Create rule**'a tıklayın ve kural türü olarak **Keywords**'ü seçin. 2. Açıklayıcı bir **Rule name** girin. 3. **Apply to** bölümünde, kuralın geçerli olacağı kampanya gruplarını, uygulamaları, kampanyaları veya reklam gruplarını seçin. 4. **Add condition**'a tıklayın ve listeden bir [metrik](adapty-ads-manager-metrics) seçin. Metrikler, hesap para biriminizde seçili zaman aralığı için hesaplanır. Veriler neredeyse gerçek zamanlı olarak güncellenir, dolayısıyla kurallar her zaman güncel performans verilerini kullanır. 5. Zaman dilimini ayarlayın (örneğin Önceki 3 gün veya Önceki 7 gün), karşılaştırma operatörünü seçin ve eşik değerini girin. 6. Daha fazla koşul eklemek için **Add condition**'a tıklayın ve solda **And** veya **Or** operatörünü seçin. 7. **Action** bölümünde, koşullar karşılandığında ne olacağını seçin: **Teklifi değiştir** - **Action type**: **Increase by**, **Decrease by** veya **Set to** seçeneğini belirleyin. - **Value type**: **$** (mutlak) ile **%** (kural çalıştığı andaki mevcut teklife göre göreli) arasında geçiş yapın. - **Upper bid limit** (isteğe bağlı): Kural güçlü sinyallerde defalarca tetiklenirse aşırı teklif vermesini önlemek için maksimum teklif üst sınırı. **Anahtar kelimeyi etkinleştir** - Ek yapılandırma gerekmez. Kural, koşulları karşılayan duraklatılmış anahtar kelimeleri yeniden etkinleştirir. **Anahtar kelimeyi duraklat** - Ek yapılandırma gerekmez. Kural, koşulları karşılayan aktif anahtar kelimeleri duraklatır. **Şuraya anahtar kelime olarak ekle…** - **Target ad groups**: Kopyalanan anahtar kelimelerin ekleneceği reklam gruplarını seçin. - **CPT bid**: Kopyalanan anahtar kelimeler için başlangıç teklifini ayarlayın. - **Match type**: **Exact** veya **Broad** seçeneğini belirleyin. - **Skip if keyword already exists**: Etkinleştirildiğinde, hedef reklam grubunda zaten mevcut olan terimleri atlar. **Şuraya negatif anahtar kelime olarak ekle…** - **Scope**: Negatif anahtar kelimenin ekleneceği reklam gruplarını veya kampanyaları seçin. - **Match type**: **Exact** veya **Broad** seçeneğini belirleyin. 8. **Schedule** bölümünde: - Sıklığı seçin: **Every day**, **Every 2 days**, **Every week** vb. - Çalışma saatini seçin (tüm saatler UTC cinsindendir). Kurallar, planlanan saatte UTC olarak çalışır. Yürütme genellikle birkaç dakika içinde tamamlanır; ardından değişiklikleri Logs bölümünde ve ana kontrol panelinde görebilirsiniz. 9. Kuralı oluşturmak için **Save**'e tıklayın. ## En iyi uygulamalar \{#best-practices\} - **Dar bir kapsamla başlayın**: Davranışı doğrulamadan önce yeni kuralları önce birkaç kampanya veya reklam grubuna uygulayın, ardından genişletin. - **Aktif kampanyalar için kısa geriye dönük pencereler kullanın**: Hızlı değişen kampanyalarda genellikle 30 gün yerine 3-7 önceki gün daha iyi sonuç verir. - **Harcama ve dönüşümleri birleştirin**: Tek metrikli kurallardan kaçının. Daha güvenilir sinyaller için Harcamayı Kurulum, Deneme veya ROAS ile birlikte kullanın. - **Teklif değiştirme kurallarına teklif üst sınırı koyun**: Güçlü bir sinyal kuralı birden fazla kez tetiklediğinde teklif üst sınırı, kontrolden çıkan teklifleri önler. - **Anahtar kelimeyi etkinleştir seçeneğini kohort verileriyle kullanın**: Düşük başlangıç CPA'sı nedeniyle erken duraklatılan bir anahtar kelime, kohort verileri olgunlaştığında güçlü D31 veya D61 ROAS gösterebilir. Kohort ROAS'ı için bir koşul belirleyin ve hedefinizi geçtiğinde otomatik olarak yeniden etkinleştirin. - **Test-ölçeklendirme iş akışları için Şuraya anahtar kelime olarak ekle seçeneğini kullanın**: Test kampanyasındaki bir anahtar kelime CPA hedefinize ulaştığında, onu otomatik olarak bir ölçeklendirme kampanyasına kopyalayın. - **Discovery kampanyalarını temiz tutmak için Şuraya negatif anahtar kelime olarak ekle seçeneğini kullanın**: Bir anahtar kelime tam eşleşmeli anahtar kelime olarak onaylandığında, aynı sorgu için rekabeti önlemek amacıyla Discovery veya Search Match kampanyalarınızda negatif olarak ekleyin. - **Yeni eklenen anahtar kelimelerde teklif kurallarının devreye girmesini bekleyin**: Terimleri anahtar kelime kampanyalarına taşımak için [arama terimi otomasyonları](ads-manager-automations-search-terms) kullanıyorsanız, bu anahtar kelimelere veri biriktirmeleri için önce bir-iki gün süre tanıyın. --- # File: ads-manager-automations-search-terms --- --- title: "Adapty Ads Manager'da arama terimi otomasyonları" description: "Keşif trafiğini manuel çaba harcamadan ölçeklendirmek için kazanan arama terimlerini otomatik olarak anahtar kelime olarak ekleyin ve kaynakta reddedin" --- Discovery ve Search Match kampanyaları arama terimi verisi üretir. Bu veriyi yapılandırılmış bir anahtar kelime listesine dönüştürmek; raporları indirmeyi, terimleri filtrelemeyi ve bunları reklam gruplarına manuel olarak eklemeyi gerektirir. Arama terimi otomasyonları bunu otomatik olarak yapar: bir terim koşullarınızı karşıladığında, kural yapılandırdığınız aksiyonu uygular. Arama terimi kuralları için iki aksiyon türü vardır: - **Anahtar kelime olarak ekle**: Terimi hedef reklam grubunda tam eşleşme anahtar kelimesine dönüştürür ve isteğe bağlı olarak kaynak kampanyada negatife alarak mükerrer harcamayı önler. - **Negatif anahtar kelime olarak ekle**: Terimi doğrudan negatife alır, dönüştürmeden. Discovery ve Search Match kampanyalarından alakasız veya verimsiz arama terimlerini elemek için kullanın. **Anahtar kelime olarak ekle** için tipik kullanım senaryosu şu şekildedir: Discovery veya Search Match kampanyalarının gerçek kullanıcı sorgularını toplamasına izin verin, ardından belirli bir performans eşiğinin üzerindeki terimleri tespit edip kontrollü tekliflerle tanıtılan anahtar kelimeleri test etmeye ayrılmış bir Apple Search Ads kampanyası olan Probing kampanyasına tam eşleşme anahtar kelimesi olarak aktarmak için bir kural kullanın — kaynak kampanyada da negatife alarak. **Negatif anahtar kelime olarak ekle** için tipik kullanım senaryosu şudur: sık görünen ama hiç dönüşüm getirmeyen bir terim varsa (örneğin çok fazla gösterim ama sıfır tıklama), bütçe israfını durdurmak için otomatik olarak negatife alın. ## Arama terimi otomasyon kuralı oluşturma \{#create-a-search-term-automation-rule\} Arama terimi otomasyon kurallarını şablonlardan ya da sıfırdan manuel olarak oluşturabilirsiniz. :::note Kural oluşturmadan önce Discovery veya Search Match kampanyalarınızın aktif olarak çalıştığından ve arama terimi verisi topladığından emin olun. Yalnızca tam eşleşme kampanyaları arama terimi raporu oluşturmaz, dolayısıyla kural üzerinde çalışacak bir veri bulamaz. ::: ### Şablondan \{#from-a-template\} Şablondan kural oluşturmak için: 1. Sol kenar çubuğunda **Automations** bölümüne gidin ve **Templates** seçeneğine tıklayın. 2. Bir şablon seçin ve **Next** düğmesine tıklayın. 3. Önceden doldurulmuş ayarları gözden geçirin ve gerekirse düzenleyin: - **Rule name**: Otomatik olarak şablon adı ve güncel tarihle doldurulur. - **Apply to**: Kuralın arama terimlerini araması gereken kampanya gruplarını, uygulamaları, kampanyaları veya reklam gruplarını seçin. - **Conditions**: Gerekirse önceden yapılandırılmış koşulları değiştirin. - **Actions**: Gerekirse hedef reklam gruplarını, CPT teklifini ve negatif anahtar kelime kapsamını düzenleyin. - **Schedule**: Kuralın ne sıklıkla çalışacağını ayarlayın. 4. Kuralı etkinleştirmek için **Save** düğmesine tıklayın. ### Manuel olarak \{#manually\} Sıfırdan özel bir arama terimi otomasyon kuralı oluşturmak için: 1. Sol kenar çubuğunda **Automations** bölümüne gidin, **Create rule** düğmesine tıklayın ve kural türü olarak **Search terms** seçeneğini seçin. 2. Kuralın amacını tanımlayan açıklayıcı bir **Rule name** girin. 3. **Apply to** bölümünde, kuralın arama terimlerini araması gereken kampanya gruplarını, uygulamaları, kampanyaları veya reklam gruplarını seçin. 4. **Add condition** düğmesine tıklayın ve listeden bir [metrik](adapty-ads-manager-metrics) seçin. Metrikler, hesabınızdaki para birimi cinsinden seçilen zaman aralığı için hesaplanır. Veriler neredeyse gerçek zamanlı olarak güncellenir, bu nedenle kurallar her zaman güncel performans verilerini kullanır. 5. Zaman dilimini (örneğin Son 3 gün veya Son 7 gün) ayarlayın, karşılaştırma operatörünü seçin ve eşik değerini girin. 6. Daha fazla koşul eklemek için **Add condition** düğmesine tıklayın ve solda **And** veya **Or** operatörünü seçin. 7. **Action** bölümünde, bir arama terimi koşulları karşıladığında ne olacağını seçin: **Anahtar kelime olarak ekle** Eşleşen arama terimlerini hedef reklam grubunda tam eşleşme anahtar kelimesi olarak yükseltir. - **Target ad groups**: Yükseltilen anahtar kelimeleri alacak reklam gruplarını seçin. Keşif hattı oluşturmak için Probing veya diğer yapılandırılmış kampanyalardaki reklam gruplarını seçin. - **CPT bid**: Yükseltilen her anahtar kelime için başlangıç tıklama başına maliyet teklifini ayarlayın. Seçenekler: reklam grubu varsayılan teklifi, arama teriminin mevcut CPT değeri veya belirli bir değer. - **Skip if keyword already exists**: Etkinleştirildiğinde, hedef reklam grubunda zaten mevcut olan terimleri atlar. - **Add as negative**: Aynı trafiğe iki kez ödememek için aynı terimleri negatif anahtar kelime olarak ekler. - **Scope**: Negatif anahtar kelimelerin ekleneceği reklam gruplarını seçin. :::tip Aynı kuralda **Add as negative** seçeneğini etkinleştirin — terimi yapılandırılmış bir kampanyaya yükseltin ve tek adımda kaynakta negatife alın. Bu, Discovery kampanyalarınızı temiz tutar ve anahtar kelime huninizi otomatik olarak oluşturur. ::: **Negatif anahtar kelime olarak ekle** Eşleşen arama terimini yükseltmeden negatife alır. - **Scope**: Negatif anahtar kelimenin ekleneceği reklam gruplarını veya kampanyaları seçin. - **Match type**: **Exact** veya **Broad** seçin. Discovery ve Max Conversion kampanyalarından alakasız veya düşük kaliteli arama terimlerini negatife almak için bu aksiyonu kullanın. Örneğin: bir terimin 50'den fazla gösterimi varsa ve tıklama sayısı 0 ise otomatik olarak negatife alın. 8. **Schedule** bölümünde: - Sıklığı seçin: **Every day**, **Every 2 days**, **Every week** vb. - Çalışma saatini seçin (tüm saatler UTC cinsindendir). Kurallar zamanlanmış saatte UTC olarak çalışır. Yürütme genellikle birkaç dakika içinde tamamlanır; bundan sonra değişiklikleri Logs bölümünde ve ana kontrol panelinde görebilirsiniz. 9. Kuralı oluşturmak için **Save** düğmesine tıklayın. Kural çalıştıktan sonra **Automations** → **Logs** bölümüne gidin ve kuralınıza ait girişi açın. Başarılı bir çalıştırma, değerlendirilen her arama terimini kaynak kampanya, hedef reklam grubu, aksiyon sonucu ve negatife alma sonucuyla listeler. Herhangi bir terim görünmüyorsa koşullar karşılanmamıştır — eşiğinizi gözden geçirin veya geriye dönük pencereyi genişletin. ## En iyi uygulamalar \{#best-practices\} - **Kaynak olarak Discovery veya Search Match kampanyalarını kullanın**: Bu kampanya türleri gerçek kullanıcı sorgularını toplar ve kurallarınıza değerlendirmek için geniş bir arama terimi havuzu sağlar. - **Eşiğinizi geriye dönük pencerenizle eşleştirin**: 7 günde 2 veya daha fazla indirme makul bir başlangıç noktasıdır. Daha uzun bir pencere (14–30 gün) efektif çıtayı düşürür — terimler seyrek dönüşümlerle geçilebilir. Yüksek hacimli uygulamalar için pencereyi kısaltın ve eşiği yükseltin. - **Yükseltirken her zaman kaynakta negatife alın**: Bir terimi Probing kampanyasında anahtar kelime olarak ekleyip Discovery'de negatife almazsanız her iki kampanya da aynı sorgu için rekabet eder. Aynı kuralda **Add as negative** seçeneğini etkinleştirin. - **Hedef reklam gruplarını bilinçli seçin**: Yükseltilen terimleri geniş bir kampanya yerine belirli bir Probing reklam grubuna yönlendirin. Bu, anahtar kelime yapınızı temiz tutar ve performans analizini kolaylaştırır. - **Her çalıştırmanın ardından logları gözden geçirin**: Hangi terimlerin yükseltildiğini ve nereye eklendiğini doğrulamak için Logs sekmesini kontrol edin. Başlangıçta, kuralın beklediğiniz gibi davrandığını doğrulamak için kurulumun hemen ardından kuralı manuel olarak çalıştırın. Logları nasıl okuyacağınız için [Automations](ads-manager-automations#explore-logs) bölümüne bakın. - **Anahtar kelime kurallarının harekete geçmesinden önce yükseltilen anahtar kelimelere zaman tanıyın**: Aynı kampanyalarda anahtar kelime kuralları kullanıyorsanız yeni yükseltilen anahtar kelimeleri hariç tutun ya da kuralların bunlar üzerinde çalışmasından önce bir iki gün bekleyin. Performans geçmişi olmayan taze bir terim üzerinde anahtar kelime kuralı tetiklenebilir ve dönüşüm sağlamadan önce teklifini düşürebilir. - **Gösterim yoğun, sıfır tıklamalı terimler için Negatif anahtar kelime olarak ekle aksiyonunu kullanın**: Discovery ve Max Conversion kampanyaları çoğu zaman alakasız arama terimlerini yüzeye çıkarır. "Gösterimler > 50 VE Tıklamalar = 0" koşullu bir kural bunları otomatik olarak yakalar ve daha fazla wasted gösterim biriktirmeden negatife alır. ## Arama terimlerini dışa aktarma \{#export-search-terms\} Arama terimleri tablosunu CSV olarak dışa aktarmak için tablonun üzerindeki indirme simgesine tıklayın ve **Export current page** veya **Export all pages** seçeneğini belirleyin. **Export all pages** tüm sayfalardaki arama terimlerini tek bir dosya olarak indirir. Bir ilerleme modalı indirmeyi takip eder; istediğiniz zaman iptal edebilirsiniz. Tablo, görüntülemek için seçtiğiniz sütunlarla birlikte kontrol panelinizde göründüğü haliyle dışa aktarılır. --- # File: ads-manager-automations-ad-group-rules --- --- title: "Adapty Ads Manager'da reklam grubu kuralları" description: "Kampanya performansına göre reklam grubu tekliflerini ve CPA hedeflerini otomatik olarak ayarlayın, reklam gruplarını etkinleştirin veya duraklatın." --- Bir reklam grubunun ayarlarının performansına göre otomatik olarak değişmesini istediğinizde **reklam grubu kuralı** ekleyin. Tek tek anahtar kelimeler üzerinde işlem yapan anahtar kelime kurallarının aksine, reklam grubu kuralı tüm reklam grubunu bir anda etkiler. Her kural, bir koşulu bir eyleme bağlar. Örneğin: bir reklam grubu üç günde 50 dolar harcayıp deneme başlatmamışsa teklifini %20 düşür. Adapty, reklam gruplarınızı belirlediğiniz bir programa göre — saatlik, günlük, haftalık vb. — kontrol eder ve koşul sağlandığında eylemi uygular. Üstelik Adapty deneme sürümlerini, abonelikleri ve geliri takip ettiğinden, koşullarınız yalnızca kuruluma değil gerçek gelire göre yanıt verebilir. ## Mevcut koşullar \{#available-conditions\} Bir kural, bir dizi reklam grubunu izler ve performansları belirlediğiniz eşiği aştığında tetiklenir. Önce hangi reklam gruplarının izleneceğini seçin: - **Ad groups in selected campaign groups** - **Ad groups in selected apps** - **Ad groups in selected campaigns** - **Selected ad groups** Ardından kuralı tetikleyecek koşulu belirleyin. Her koşul şu parçalardan oluşur: | Bölüm | Açıklama | Örnek | | --- | --- | --- | | **Metrik** | [Adapty Ads Manager'ın takip ettiği](adapty-ads-manager-metrics) herhangi bir metrik — harcama, yükleme, deneme, abonelik, gelir ve daha fazlası. | Spend | | **Zaman penceresi** | Metriğin ölçüldüğü dönem. | Previous 3 days | | **Karşılaştırma** | Metriğin belirlediğiniz değere göre nasıl test edildiği. | is greater than | | **Eşik** | Karşılaştırma yaptığınız değer. | $50 | Hassas hedefleme için birden fazla koşulu **And** veya **Or** ile birleştirin — örneğin, spend > $50 **and** trials = 0. ## Mevcut eylemler ve ayarları \{#available-actions-and-their-settings\} Bir grup koşulunuzu karşıladığında Adapty, aşağıdaki eylemlerden birini tetikleyerek ayarlarını değiştirebilir: | Eylem | Ne yapar | Ne zaman kullanılır | Yapılandırma | | --- | --- | --- | --- | | **Change default bid** | Reklam grubunun varsayılan maksimum **tıklama başına maliyetini (CPT bid)** artırır, azaltır veya belirli bir değere ayarlar; bu, reklamınıza yapılan bir tıklama için ödeyeceğiniz en yüksek tutardır. | İyi dönüşüm sağlayan reklam gruplarını güçlendirin; dönüşüm sağlamayanları geri çekin. | **Action type**: Increase by, Decrease by veya Set to.<br/>**Value type**: $ (mutlak) veya % (mevcut teklifin yüzdesi).<br/>**Limit** (isteğe bağlı): Artırırken üst sınır, azaltırken alt sınır — tekrarlanan çalıştırmaların teklifi ne kadar değiştireceğini sınırlar. | | **Change CPA goal** | Reklam grubunun **CPA hedefini (üst sınır)** artırır, azaltır veya belirli bir değere ayarlar; hedef, edinme başına maliyettir. | Optimize ederken maliyet tavanını sıkılaştırın ya da daha fazla hacim kazanmak için gevşetin. | **Action type**: Increase by, Decrease by veya Set to.<br/>**Value type**: $ veya %.<br/>**Limit** (isteğe bağlı): Artırırken üst sınır, azaltırken alt sınır. | | **Enable ad group** | Duraklatılmış bir reklam grubunu yeniden etkinleştirir. | Geç gelen deneme ve abonelik geliri aktıktan sonra toparlanma gösteren reklam gruplarını geri getirin. | Yok. | | **Pause ad group** | Aktif bir reklam grubunu duraklatır. | Dönüşüm sağlamadan harcamaya devam eden reklam gruplarını durdurun. | Yok. | ## Reklam grubu kuralı oluşturma \{#create-an-ad-group-rule\} 1. **Automations** bölümüne gidin, **Create rule** düğmesine tıklayın ve **For ad groups** seçeneğini seçin. 2. Bir **Rule name** girin. 3. **Apply to** bölümünde bir [kapsam](#available-conditions) seçin ve reklam gruplarını belirleyin. 4. **Conditions** bölümünde bir veya daha fazla [koşul](#available-conditions) ekleyin. Koşulları mantıksal operatörlerle birleştirebilirsiniz. 5. **Action** bölümünde bir [aksiyon](#available-actions-and-their-settings) seçin ve seçeneklerini ayarlayın. 6. **Schedule** bölümünde kuralın ne sıklıkla çalışacağını ve başlangıç saatini (UTC) ayarlayın ya da **Run immediately** seçeneğini belirleyin. 7. **Save** düğmesine tıklayın. Kaydettikten sonra kural, **Automations** sekmesinde görünür. **Date last run** ve **Date next run** sütunları kuralın zamanlamasını takip eder. Çalıştırmalar arasındaki durum değişikliklerini onaylamak için **Automations > Logs** bölümünü açın. Bir kuralı duraklatmak, kopyalamak, silmek veya hemen çalıştırmak için [Automations](ads-manager-automations) sayfasındaki talimatlara bakın. --- # File: ads-manager-automations-campaign-rules --- --- title: "Adapty Ads Manager'da kampanya kuralları" description: "Kampanya günlük bütçelerini otomatik olarak ayarlayın ve kampanyaları performansa göre etkinleştirin veya duraklatın." --- Bir kampanyanın bütçesinin veya durumunun performansına göre otomatik olarak değişmesini istediğinizde **kampanya kuralı** ekleyin. Tek bir reklam grubuna etki eden reklam grubu kurallarının aksine, kampanya kuralı tüm kampanyayı bir anda değiştirir. Her kural, bir koşulu bir eylemle eşleştirir. Örneğin: bir kampanya üç günde 200 dolar harcayıp abonelik getirmediyse, günlük bütçesini %20 düşür. Adapty, kampanyalarınızı belirlediğiniz bir programa göre —saatlik, günlük, haftalık vb.— kontrol eder ve koşul her sağlandığında eylemi uygular. Adapty deneme sürelerini, abonelikleri ve geliri takip ettiğinden, koşullarınız yalnızca kurulumları değil, gerçek geliri esas alabilir. ## Mevcut koşullar \{#available-conditions\} Bir kural, belirli kampanyaları izler ve performansları belirlediğiniz eşiği aştığında tetiklenir. Önce hangi kampanyaların izleneceğini seçin: - **Campaigns in selected campaign groups** - **Campaigns in selected apps** - **Selected campaigns** Ardından kuralı tetikleyecek koşulu belirleyin. Her koşul şu parçaları bir araya getirir: | Bölüm | Açıklama | Örnek | | --- | --- | --- | | **Metrik** | [Adapty Ads Manager'ın takip ettiği](adapty-ads-manager-metrics) herhangi bir metrik — harcama, kurulum, deneme, abonelik, gelir ve daha fazlası. | Spend | | **Zaman dilimi** | Metriğin ölçüldüğü dönem. | Yesterday | | **Karşılaştırma** | Metriğin değerinizle nasıl test edildiği. | is greater than | | **Eşik değeri** | Karşılaştırma yapılan değer — sabit bir miktar veya kampanyanın kendi **Daily Budget**'ı. | Daily Budget | Hassas hedefleme için birden fazla koşulu **And** veya **Or** ile birleştirin — örneğin, harcama > Günlük Bütçe **and** ROAS < %100. ## Mevcut eylemler ve ayarları \{#available-actions-and-their-settings\} Bir kampanya koşulunuzu karşıladığında Adapty, aşağıdaki eylemlerden birini tetikleyerek kampanyanın ayarlarını değiştirebilir: | Eylem | Ne yapar | Ne zaman kullanılır | Yapılandırma | | --- | --- | --- | --- | | **Change daily budget** | Kampanyanın **günlük bütçesini** — günlük maksimum harcama limitini — artırır, azaltır veya belirli bir değere ayarlar. | Aşırı harcama yapan kampanyaların bütçesini kısın; kârlı büyüyen kampanyaların bütçesini artırın. | **Action type**: Increase by, Decrease by veya Set to.<br/>**Value type**: $ (mutlak değer) veya % (mevcut bütçenin yüzdesi).<br/>**Limit** (isteğe bağlı): Artırırken üst sınır, azaltırken alt sınır — tekrarlanan çalıştırmaların bütçeyi ne kadar değiştirebileceğini sınırlar. | | **Enable campaign** | Duraklatılmış bir kampanyayı yeniden etkinleştirir. | Geç gelen deneme ve abonelik geliri yerleşince iyileşen kampanyaları geri getirin. | Yok. | | **Pause campaign** | Aktif bir kampanyayı duraklatır. | Dönüşüm sağlamadan harcamaya devam eden kampanyaları durdurun. | Yok. | ## Kampanya kuralı oluşturma \{#create-a-campaign-rule\} Hazır bir şablonla başlamak için **Automations** başlığındaki **Templates** seçeneğine tıklayıp **Decrease budget for low-performing campaigns** şablonunu seçin, ardından gözden geçirip kaydedin. Sıfırdan kural oluşturmak için: 1. **Automations** bölümüne gidin, **Create rule** düğmesine tıklayın ve **For campaigns** seçeneğini seçin. 2. Bir **Rule name** girin. 3. **Apply to** bölümünde bir [kapsam](#available-conditions) seçin ve kampanyaları belirleyin. 4. **Conditions** bölümünde bir veya daha fazla [koşul](#available-conditions) ekleyin. Koşulları mantıksal operatörlerle birleştirebilirsiniz. 5. **Action** bölümünde bir [eylem](#available-actions-and-their-settings) seçin ve seçeneklerini ayarlayın. 6. **Schedule** bölümünde kuralın ne sıklıkla çalışacağını ve başlangıç saatini (UTC) ayarlayın ya da **Run immediately** seçeneğini seçin. 7. **Save** düğmesine tıklayın. Kaydettikten sonra kural, **Automations** sekmesinde görünür. **Date last run** ve **Date next run** sütunları kuralın zamanlamasını takip eder. Çalıştırmalar arasındaki durum değişikliklerini onaylamak için **Automations > Logs** bölümünü açın. Bir kuralı duraklatma, kopyalama, silme veya hemen çalıştırma talimatları için [Automations](ads-manager-automations) sayfasına bakın. --- # File: ads-manager-market-intelligence --- --- title: "Adapty Ads Manager'da Pazar İstihbaratı" description: "Rakiplerinizin 50'den fazla ülkede hangi anahtar kelimeler üzerinde Apple Ads yayınladığını görün ve bunları doğrudan kampanyalarınıza ekleyin." --- Market Intelligence, rakiplerinizin Apple Ads'te hangi anahtar kelimelere teklif verdiğini 50'den fazla ülkede gösterir. Veriler son 30 günden derlenir ve her gün güncellenir. Şunlar için kullanabilirsiniz: - **Discovery kampanyasını atlayın**: Ne işe yaradığını bulmak için bütçe harcamak yerine rakiplerinizin halihazırda teklif verdiği anahtar kelimelere bakın. İlk günden kanıtlanmış bir anahtar kelime listesiyle başlayın. - **Düşük rekabetli anahtar kelimeler bulun**: Rakiplerin Ses Payı'nın (Share of Voice) düşük olduğu uzun kuyruklu terimleri tespit edin — daha az rekabet, tıklama başına daha düşük maliyet ve daha iyi CPA. - **Markanızı koruyun**: Rakiplerin hangi ülkelerde uygulama adınız üzerinde teklif verdiğini görün ve bu trafiği geri kazanın. - **Veriye dayalı yeni pazarlara girin**: Bir ülkeye bir kuruş harcamadan önce rakiplerinizin orada hangi anahtar kelimeleri kullandığını kontrol edin. - **Gözden kaçırdığınız rakipleri keşfedin**: Kategorinizdeki terimler için organik sıralamada kimlerin yer aldığını görmek amacıyla anahtar kelimeye göre arama yapın ve onları analizinize ekleyin. ## Market Intelligence analizi çalıştırma \{#run-a-market-intelligence-analysis\} ### 1. Uygulamanızı seçin \{#1-select-your-app\} Sol kenar çubuğunda **Market Intelligence** bölümüne gidin. Açılır menüden analiz etmek istediğiniz uygulamayı seçin, ardından **Continue** düğmesine tıklayın. ### 2. Rakipleri seçin \{#2-select-competitors\} Analiz etmek istediğiniz rakipleri ekleyin: - **Önerilen rakipler**: Adapty, uygulama kategorinize göre olası rakipleri otomatik olarak tespit eder. Listeyi inceleyin ve dahil etmek istediklerinizi seçin. - **Anahtar kelime veya uygulama adıyla arama**: Arama alanına bir anahtar kelime (örneğin "budget tracker") veya uygulama adı girin. Gerekirse ülkeyi değiştirin, ardından sonuçlardan uygulamaları seçin. Farklı arama niyetlerine sahip rakipleri keşfetmek için farklı anahtar kelimelerle aramayı tekrarlayın. - **Kayıtlı liste**: Gelecekteki analizlerde tekrar kullanmak üzere 20'ye kadar rakip kaydetmek için **Create list** seçeneğine tıklayın. Daha önce oluşturduğunuz bir listeyi de yükleyebilirsiniz. Rakiplerinizi seçtikten sonra **Run analysis** düğmesine tıklayın. ### 3. Sonuçları inceleyin \{#3-explore-results\} Sonuçlar dört sekme halinde düzenlenir: **Overview**, **Most Contested**, **By App** ve **By Country**. #### Overview \{#overview\} Varsayılan sekme, analizin özetini gösterir: - **İstatistik çubuğu**: Analiz edilen toplam rakip sayısı, Apple Ads faaliyeti olan ülkeler, tüm pazarlarda bulunan benzersiz anahtar kelimeler ve en çok rekabet edilen tek anahtar kelime. - **Ülkeye göre bulunan anahtar kelimeler**: İlk 25 pazardaki ülke başına anahtar kelime hacmini gösteren bir çubuk grafik. - **Anahtar kelime kapsamına göre ilk 10 rakip**: Her rakibin toplam anahtar kelime sayısını, ortalama Ses Payı'nı (Avg SOV) ve aktif oldukları ülkeleri gösteren sıralı bir tablo. #### Most Contested \{#most-contested\} En fazla sayıda rakibin aynı anda aktif olduğu anahtar kelimeleri gösterir. Kategorinizdeki yüksek talep gören terimleri bulmak ve rekabetin en yoğun olduğu yerleri görmek için bu sekmeyi kullanın. Listeyi anahtar kelimeye göre filtrelemek için arama alanını kullanın. #### By App \{#by-app\} Her rakip için anahtar kelime verilerini ayrı ayrı gösterir. Belirli bir uygulamanın ülkeler genelindeki anahtar kelime stratejisini derinlemesine incelemek için bu sekmeyi kullanın. Uygulamaya, ülkeye veya anahtar kelimeye göre filtrelemek için **Add filter** seçeneğine tıklayın. Verileri CSV olarak dışa aktarmak için indirme simgesine tıklayın. #### By Country \{#by-country\} Anahtar kelime verilerini pazara göre gruplandırarak gösterir. Bir ülkeye girmeden veya orada büyümeden önce o ülkenin rekabet ortamına odaklanmak istediğinizde bu sekmeyi kullanın. Uygulamaya, ülkeye veya anahtar kelimeye göre filtrelemek için **Add filter** seçeneğine tıklayın. Verileri CSV olarak dışa aktarmak için indirme simgesine tıklayın. ### 4. Kampanyalara anahtar kelime ekleyin \{#4-add-keywords-to-campaigns\} Test etmeye değer anahtar kelimeleri belirledikten sonra, aracı terk etmeden bunları kampanyalarınıza ekleyin: 1. Anahtar kelime tablosunda, kullanmak istediğiniz anahtar kelimelerin yanındaki onay kutularını seçin. Görünür tüm anahtar kelimeleri seçmek için tablo başlığındaki onay kutusunu kullanın. 2. **Add to campaign** düğmesine tıklayın. 3. Bunları anahtar kelime, negatif anahtar kelime veya SKAG olarak ekleyip eklemeyeceğinizi seçin. Ardından hedef kampanyayı ve reklam grubunu seçin, eşleşme türünü ve CPT teklifini belirleyin, ardından onaylayın. ## Nelere dikkat edilmeli \{#what-to-look-for\} Sonuçlarda şu kalıplara dikkat etmek faydalıdır: - **Düşük Ses Payına sahip uzun kuyruklu terimler**: Rakiplerin düşük gösterim payına sahip olduğu anahtar kelimeler daha az rekabetlidir. Kullanıcı niyeti daha spesifik olduğundan genellikle tıklama başına daha düşük maliyete ve daha iyi dönüşüm oranlarına sahiptirler. - **Kampanyalarınızda henüz yer almayan anahtar kelimeler**: Rakiplerinizin kullandığı ancak siz henüz denemediğiniz terimleri arayın. Bunların kategorinizdeki Apple Ads trafiğini yönlendirdiği kanıtlanmıştır. - **Marka anahtar kelime kapsamı**: Kendi uygulama adınızı arayın. Rakipler görünüyorsa markanız üzerinde teklif veriyorlar demektir. Trafiğinizi korumak için bu anahtar kelimeleri agresif tekliflerle kampanyalarınıza ekleyin. - **Ülke boşlukları**: Rakiplerinizin hangi ülkelerde aktif olduğunu kontrol edin. Rakip faaliyetinin az ya da hiç olmadığı pazarlara girmek daha kolaydır ve ivme kazanmak için daha az bütçe gerektirir. --- # File: ads-manager-cpp-ab-tests --- --- title: "Adapty Ads Manager'da CPP A/B Testleri" description: "Apple Ads'te özel ürün sayfalarını karşılaştırın ve en iyi performansı göstereni bulun." --- CPP A/B Testleri, Apple Ads içinde özel ürün sayfalarını (CPP'leri) birbiriyle karşılaştırmanıza olanak tanır. 2 ile 4 arasında ürün sayfası seçersiniz; [Adapty Ads Manager](adapty-ads-manager) trafiği bunlar arasında dönüşümlü olarak dağıtır, performans verilerini toplar ve hangi sayfanın en iyi dönüşümü sağladığını gösterir. **Varsayılan ürün sayfanızı** varyantlardan biri olarak ekleyebilirsiniz; böylece özel bir sayfanın mevcut varsayılanınızdan daha iyi performans gösterip göstermediğini test edebilirsiniz. ## Ön Koşullar \{#prerequisites\} CPP A/B testi oluşturmadan önce şunlara dikkat edin: - **Apple Ads Manager bağlı olmalı**: Henüz yapmadıysanız [kurulum kılavuzunu](adapty-ads-manager-get-started) takip edin. - **Kaynak reklam grubunda trafik olmalı**: Test ettiğiniz reklam grubu en az 28 günlük olmalı ve bu süre içinde gösterim, dokunma ve kurulum verisi bulunmalıdır. Apple Ads Manager, test süresini ve gerekli örneklem boyutunu tahmin etmek için bu geçmişi kullanır. - **En az bir özel ürün sayfanız olmalı**: CPP'leri önce App Store Connect'te oluşturun. Apple Ads Manager bunları otomatik olarak okur. ## CPP A/B testi oluşturma \{#create-a-cpp-ab-test\} Bir test oluşturmak için sol kenar çubuğundan **CPP A/B Tests** bölümüne gidin ve **Create A/B Tests** düğmesine tıklayın. Sihirbaz dört adımdan oluşur: **Ad Group(s)**, **Ad Creative(s)**, **Testing Method** ve **Review**. ### 1. Reklam Grubu(ları) \{#1-ad-groups\} Bir **Test Adı** girin ve hangi reklam grubunun CPP'lerini test etmek istediğinizi seçmek için **Select Ad Group** seçeneğine tıklayın. Aynı kampanyadan en fazla dört reklam grubu seçebilirsiniz; ancak bu yalnızca tek bir reklam görseli test edecekseniz geçerlidir. Birden fazla CPP'yi karşılaştırmak için tek bir reklam grubu seçin. ### 2. Reklam Görseli(leri) \{#2-ad-creatives\} Karşılaştırmak istediğiniz CPP'leri seçin. **Kontrol** olarak işaretlenen **Varsayılan Ürün Sayfası**'na ek olarak en fazla üç **Özel Ürün Sayfası** ekleyebilirsiniz; toplamda 2 ile 4 varyant olacak şekilde. - **Varsayılan Ürün Sayfası**: Mevcut varsayılan ürün sayfanızı kontrol varyantı olarak eklemek için **+ Add Default** seçeneğine tıklayın. - **Özel Ürün Sayfaları**: App Store Connect'ten bir özel ürün sayfası seçmek için **+ Select CPP** seçeneğine tıklayın. ### 3. Test Yöntemi \{#3-testing-method\} Testin nasıl çalışacağını yapılandırın. Adapty Ads Manager, **Calculated Test Duration**, **Start Time** ve **End Time** değerlerini otomatik olarak hesaplar — aşağıdaki üç ayardan birini değiştirdiğinizde değerler güncellenir. #### Switch Time Preset \{#switch-time-preset\} Sistemin varyantlar arasında ne sıklıkla geçiş yapacağını belirler. Trafik düzeyine göre çok yüksek bir değer seçerseniz sistem bunu otomatik olarak düşürür. | Aralık | Tipik trafik seviyesi | Slot süresi | Tipik test uzunluğu | |--------------|----------------------------------------|---------------|---------------------| | **Saatlik** | Yüksek (günde 5.000+ gösterim) | 7 saat | Günler | | **Günlük** | Normal | 24 saat | Haftalar | | **Haftalık** | Düşük (günde 400'den az gösterim) | 7 gün | Aylar | **Slot**, sistemin bir sonrakine geçmeyi değerlendirmeden önce bir varyantın çalıştığı temel süredir. #### İstenen Hassasiyet \{#desired-precision\} Testin güvenilir biçimde algılayabileceği en küçük dönüşüm oranı farkı. Seçenekler: **%1**, **%2**, **%3**, **%4**, **%5**. Varsayılan: **%5**. %1 hassasiyetle çalışan bir test küçük farkları bile yakalar, ancak daha fazla veriye ihtiyaç duyar ve daha uzun sürer. %5 hassasiyetle çalışan bir test daha hızlı tamamlanır, ancak yalnızca büyük farkları yakalar. | Hassasiyet | Ne zaman kullanılır | |------------|----------------------------------------------------------------------------------------------| | 1–2% | CPP'ler arasında küçük farklar bekliyorsunuz ve yüksek trafikli reklam gruplarınız var. | | 3–4% | Çoğu test için dengeli varsayılan değer. | | 5% | Net bir kazanan bekliyorsunuz ve sonuçları hızlı almak istiyorsunuz. | #### Güven Düzeyi \{#confidence-level\} Sonucun gerçek olduğundan ve rastgele gürültüden kaynaklanmadığından ne kadar emin olmak istediğinizi belirtir. Seçenekler: **80%**, **85%**, **90%**, **95%**, **99%**. Varsayılan: **90%**. Daha yüksek bir güven düzeyi daha fazla veri gerektirir. | Güven | Denge | |-------|-------| | 80–85% | Daha hızlı sonuç verir, ancak sonucun rastlantısal olma ihtimali daha yüksektir. | | 90% | Çoğu test için önerilen varsayılan değer. | | 95–99% | En muhafazakâr seçenek. En fazla veri ve en uzun test süresi gerektirir. | ### 4. İnceleme \{#4-review\} Özeti doğrulayın — seçili reklam grupları, kreatifler, test yöntemi, süre, hassasiyet ve güven düzeyi — ardından **Start CPP A/B Tests** butonuna tıklayın. Testi başlattıktan sonra sistem her varyant için reklam grubunu kopyalar, ilk varyantı etkinleştirir ve test durumu birkaç dakika içinde **Running** olarak güncellenir. ## Çalışan bir testi izleme \{#monitor-a-running-test\} Test listesini açmak için sol kenar çubuğundaki **CPP A/B Tests** bölümüne gidin. Sayfanın üstündeki dört sekme, testleri duruma göre filtreler: - **Live**: Şu anda çalışan testler. - **Completed**: Tamamlanmış testler. - **Draft**: Henüz başlatılmamış testler. - **Archive**: Artık ana görünümde ihtiyaç duymadığınız eski testler. Her test kartı; testin adını, durumunu, geçiş aralığını, istenen hassasiyeti ve ne kadar süredir çalıştığını gösterir. Varyant tablosunu genişletmek için **View metrics** seçeneğine tıklayın. ### Varyant performansı \{#variant-performance\} Varyant tablosu, testteki tüm varyantların performansını karşılaştırır: | Sütun | Açıklama | |--------------------------|-----------------------------------------------------------------------------------------------------| | **Variant Name** | Test edilen CPP. A varyantı her zaman eklediğiniz ilk varyantdır. | | **Confidence Level** | Varyantın gerekli örneklem büyüklüğüne ne kadar yakın olduğu; 0'dan 100'e kadar yüzde olarak. | | **Impressions** | Apple'ın bu varyant için bir reklam gösterme sayısı. | | **TTR** | Tıklama oranı: tıklamalar gösterimlere bölünür. | | **Tap → Download CR** | Tıklamadan indirmeye dönüşüm. | | **CPT** | Tıklama başına ortalama maliyet. | | **Avg CPA (Tap-Through)**| Tıklama yoluyla gerçekleşen indirmelere dayalı edinim başına ortalama maliyet. | | **Spend** | Varyanta atfedilen toplam harcama. | | **Revenue** | Varyanta atfedilen toplam gelir. | | **ROAS** | Reklam harcamalarından elde edilen gelir: gelir, harcamaya bölünür. | Her varyant karşılaştırılabilir gösterim sayısına ulaşana kadar Adapty Ads Manager bir kazananı öne çıkarmaz. Veriler hâlâ toplanırken tablonun üzerinde şu banner'ı görürsünüz: **Winner highlighting is paused — variants don't have comparable impressions yet.** ### Ayrıntılı metrikler \{#detailed-metrics\} Teste daha ayrıntılı bakmak için **View metrics** düğmesine tıklayarak ayrıntılı metrikler sayfasını açın. Bu sayfada kohort tutma eğrileri, ARPPU karşılaştırması ve iki bölüme ayrılmış bir metrik tablosu yer alır: - **Top of funnel · Apple Search Ads**: Her varyant için TTR, Download Rate, CPM, CPT ve Avg CPA. - **Bottom of funnel · Monetization**: Her varyant için Paid users, Paid CR, Cost per Paid, ARPPU, Revenue ve ROAS. **Kazanan** sütunu, her metrikteki öncü varyantı gösterir. Bir varyant, yalnızca birincil metrikte öne geçtiğinde ve en az %95 güven düzeyine ulaştığında genel kazanan olarak işaretlenir. Metrik tanımları için bkz. [Adapty Ads Manager'daki metrikler](adapty-ads-manager-metrics). ## Testi durdurma \{#stop-a-test\} Bir testi istediğiniz zaman durdurabilirsiniz. Test **Stopped** olarak işaretlenir, orijinal reklam grubu geri yüklenir ve kopyalanan reklam grupları duraklatılır. Çalışan bir testi durdurmak için: 1. Sol kenar çubuğunda **CPP A/B Tests** bölümüne gidin. 2. Test kartında **Stop A/B test** seçeneğine tıklayın ya da testi açıp **Stop Test** butonuna tıklayın. 3. **Stop A/B Test?** iletişim kutusunda onaylayın. :::important Testi durdurmak geri alınamaz — testi yeniden başlatamazsınız. O ana kadar toplanan sonuçlar **Completed** sekmesinde görüntülenmeye devam eder. ::: ## Test durumları \{#test-statuses\} Her test, sabit bir durum sırasından geçer: | Durum | Anlam | |---------------|------------------------------------------------------------------------------------------| | **Draft** | Test oluşturuldu ancak başlatılmadı. Hâlâ düzenleyebilirsiniz. | | **Starting** | Kurulum devam ediyor — sistem reklam gruplarını kopyalıyor ve reklamlar oluşturuluyor. | | **Running** | Test yayında. Varyantlar döndürülüyor ve metrikler toplanıyor. | | **Completed** | Planlanan süre doldu veya güven eşiğine ulaşıldı. Orijinal reklam grubu geri yüklendi. | | **Stopped** | Testi manuel olarak durdurdunuz. Orijinal reklam grubu geri yüklendi. | | **Failed** | Kurulum başarısız oldu veya çok fazla ardışık hata oluştu. Başarısız testi yeniden başlatabilirsiniz. | ## Nasıl çalışır \{#how-it-works\} Adapty Ads Manager **Ad Group Switch** yöntemini kullanır: 1. Test başladığında, sistem kaynak reklam grubunu her varyant için bir kez kopyalar. Her kopya farklı bir CPP'ye işaret eder (bunlardan biri varsayılan sayfanız olabilir). 2. Aynı anda yalnızca bir kopya çalışır. Sistem, sabit bir programa göre (saatlik, günlük veya haftalık) hangi kopyanın aktif olduğunu döndürür. 3. Test süresince orijinal reklam grubu duraklatılır. Test sona erdiğinde önceki durumuna geri yüklenir. 4. Adapty Ads Manager, varyant başına gösterim, dokunma ve indirme verilerini toplar; her varyantın istatistiksel olarak anlamlı bir örneğe ne kadar yakın olduğunu takip eder. 5. Test, her varyant yeterli veriye ulaştığında otomatik olarak sona erer ya da planlanan süre dolduğunda biter. ## Test çalışırken neler beklenmeli \{#what-to-expect-while-a-test-runs\} Çalışan bir testin kontrol panelinde nasıl davrandığını bilmekte fayda var: - **Varyantlar sabit bir takvime göre değişmez**: Geçiş aralığı bir başlangıç noktasıdır, ancak Adapty Ads Manager her varyantın adil bir izlenim payı toplaması için zamanlamayı ayarlar. Bir varyant, izlenim açısından geride kalıyorsa bir dilimden daha uzun süre aktif kalabilir. - **Bitiş Zamanı ileriye taşınabilir**: Planlanan bitiş yaklaşırken bir varyantın verisi yetersiz kalıyorsa, tıklama toplamaya devam etmek için test otomatik olarak uzatılır. Yeni Bitiş Zamanı test kartında görünür. - **Test sona erdiğinde orijinal reklam grubu geri yüklenir**: Kopyalanan tüm reklam grupları duraklatılır ve kaynak reklam grubu test öncesi durumuna döner. Sonuçlar **Completed** sekmesinde görüntülenmeye devam eder. --- # File: ads-manager-settings --- --- title: "Adapty Ads Manager'da Ayarlar" description: "Adapty Ads Manager'da ayarları yapılandırın." --- Hesap ayarlarınızı yapılandırmak için Adapty Ads Manager kontrol panelinin sol alt köşesindeki **Settings** bölümüne gidin. ## Kampanya grupları \{#campaign-groups\} **Campaign groups** sekmesinde, Adapty Ads Manager'a bağlı tüm Apple Ads hesaplarını görebilir ve yeni hesap ekleyebilirsiniz. Birden fazla Apple Ads hesabı bağlarsanız, tüm bu hesapların analizleri tek bir Adapty Ads Manager kontrol panelinde bir araya getirilir. Yeni bir Apple Ads hesabı eklemek için **Connect Apple Ads account** düğmesine tıklayın ve [kılavuzu](adapty-ads-manager-get-started) izleyin. ## Aboneliği yönet \{#manage-subscription\} **Manage subscription** sekmesinde mevcut abonelik planınızı görebilir ve ödeme yönteminizi güncelleyebilirsiniz. ## Kullanıcı ayarları \{#user-settings\} **User settings** sekmesinde **Hide Paused by Default** anahtarını açabilirsiniz. Bu seçenek etkinleştirildiğinde, duraklatılmış kampanyalar, reklam grupları ve anahtar kelimeler gizlenerek aktif performans verilerine odaklanmanız kolaylaşır. Farklı kampanyaları, reklam gruplarını ve anahtar kelimeleri sık sık başlatıp duraklatarak deneme yapıyorsanız bu seçeneği etkinleştirmekten kaçının; duraklatılmış öğelere istediğiniz zaman erişmek isteyebilirsiniz. --- # File: adapty-user-acquisition --- --- title: "Adapty Attribution" description: "MMP'lere olan ihtiyacı ortadan kaldırın ve tüm uygulama ekonomisini tek bir yerde hesaplayın." --- <CustomDocCardList ids={['user-acquisition', 'ua-analytics', 'ua-integrations', 'ua-tracking-links', 'ua-deferred-data']} /> Adapty Attribution, reklam platformları, izleme bağlantıları ve uygulamanızdan gelen verileri birleştirerek reklam kampanyalarını uygulama yüklemeleri ve abonelik gelirleriyle ilişkilendiren bir attribution çözümüdür. Tüm edinim verilerinizi tek bir yerde toplayan birleşik bir pazarlama analitiği kontrol paneli sunar. - Tüm kanallarınızda ROAS (reklam harcamalarından elde edilen gelir) hesaplayın - Tüm uygulama ekonominizi tek bir yerden görüntüleyin - Daha iyi kararlar almak için doğru attribution verileri elde edin - Kohort performansını ve kullanıcı davranışını zaman içinde analiz edin :::tip Adapty Attribution'ın size nasıl fayda sağlayabileceği hakkında daha fazla bilgi edinmek ister misiniz? Bizimle bir [görüşme planlayın](https://calendly.com/tnurutdinov-adapty/30min). ::: ## Neden Adapty Attribution'ı Seçmelisiniz? \{#why-choose-adapty-attribution\} Kullanıcı edinimi performansını ölçmek zorludur. Veriler çoğunlukla platformlara dağılmış olur, gizlilik değişiklikleri nedeniyle attribution güçleşir ve özel çözümler geliştirmek ciddi zaman alır. Adapty Attribution, tek bir pazarlama kontrol panelinde yerleşik attribution ve birleşik analitik sunar. Reklam harcamalarından kurulumlardan abonelik gelirine kadar tüm müşteri kazanım metrikleriniz otomatik olarak birleştirilir ve gerçek zamanlı olarak güncellenir. Artık elektronik tablolardaki verileri uzlaştırmanıza ya da birden fazla araç arasında geçiş yapmanıza gerek yok. Veri sistemlerini yönetmek yerine uygulamanızı büyütmeye odaklanabilirsiniz. ## Nasıl çalışır \{#how-it-works\} Adapty Attribution, reklam kampanyalarına uygulama yüklemelerini ve abonelik gelirlerini; reklam platformlarından, takip bağlantılarından ve uygulamanızdan gelen verileri birleştirerek ilişkilendirir. Genel bakışta: - Reklam platformları kampanya yapısını ve reklam harcamasını sağlar - Adapty Attribution'da oluşturulan takip bağlantıları, kampanya bağlamını web'den uygulama yüklemesine taşır - Adapty SDK, uygulamanızdan yükleme ve gelir olaylarını gönderir Attribution flow'u şu şekilde işler: 1. **Adapty Attribution'da bir takip bağlantısı oluşturulur ve bir reklam kampanyasına eklenir.** Bağlantı; platform, kampanya, reklam seti ve kreatif gibi kampanya parametrelerini içerir. 2. **Kullanıcı reklamı tıklar ve uygulamayı uygulama mağazasından yükler.** Kullanıcı, takip bağlantısı aracılığıyla yönlendirilir ve uygulamayı App Store veya Google Play'den yükler. 3. **Uygulama, Adapty'ye bir yükleme olayı gönderir.** İlk açılışta Adapty SDK, bir yükleme olayı gönderir. Adapty, bu yüklemeyle ilişkili kampanya parametrelerini çıkarır. 4. **Yükleme bir kampanyaya atfedilir.** Takip bağlantısındaki kampanya parametrelerini kullanarak Adapty, yüklemeyi onu oluşturan kampanyayla ilişkilendirir. 5. **Reklam harcamaları ve gelirler birbirine bağlanır.** Adapty, desteklenen reklam platformlarından (şu an için Meta Ads ve TikTok for Business) reklam harcama verilerini çeker ve abonelik ile satın alma olaylarını atfedilen yüklemelerle ilişkilendirir. Sonuç olarak Adapty, birleşik bir analitiği kontrol panelinde yükleme, gelir, LTV ve ROAS gibi kampanya düzeyinde metrikler sunar. Farklı kaynaklardan gelen verileri manuel olarak karşılaştırmaya gerek kalmadan kohortları analiz edebilir, performansı zaman içinde takip edebilir ve veriye dayalı optimizasyon kararları alabilirsiniz. :::tip Takip bağlantıları özel parametreler de içerebilir; bu sayede uygulamanız yükleme olayını işlerken [ertelenmiş derin bağlantıları](ua-deferred-data) yönetebilir ve kampanya verilerine tepki verebilir. ::: --- # File: user-acquisition --- --- title: "Adapty Attribution'a Başlarken" description: "Reklam harcamalarını ve abonelik gelirlerini birleştirmek ve tüm uygulama ekonomisini tek bir yerden görmek için Adapty Attribution ile bağlantı kurun." --- Adapty Attribution, web-to-app kampanyalarında reklam harcamalarını abonelik gelirleriyle ilişkilendirmenize yardımcı olur ve uygulamanızın ekonomisini tek bir yerden eksiksiz görmenizi sağlar. Gelir verilerinizi Adapty Attribution'da görmek için önce Adapty kontrol panelinde entegrasyonu etkinleştirmeniz gerekir. Herhangi bir API anahtarı, token veya tanımlayıcı girmenize gerek yoktur. Sadece Adapty SDK'yı güncelleyip yapılandırın. :::important Adapty Attribution şunlarla kullanılabilir: - iOS, Android ve Flutter SDK sürüm 3.9.1 veya üzeri. - React Native ve Capacitor SDK sürüm 3.10.0 veya üzeri. - Unity SDK sürüm 3.12.0 veya üzeri. - Kotlin Multiplatform SDK sürüm 3.15.0 veya üzeri. ::: ## Başlamadan önce \{#before-you-start\} Gelir verilerinizi kampanya performansıyla ilişkilendirmek için Adapty'nin satın almalarınızı takip etmesine izin verin: - Eğer **Adapty ile uygulama içi satın almaları zaten uyguladıysanız**, bu aşamada başka bir şey yapmanıza gerek yok. - Eğer **henüz uygulama içi satın almaları uygulamadıysanız ve Adapty kullanmak istiyorsanız**, satın alma işlemlerini Adapty'ye devretmek için [hızlı başlangıç kılavuzundaki](quickstart) adımları tamamlayın. - Eğer **Adapty olmadan uygulama içi satın almaları zaten uyguladıysanız** ve Adapty'ye geçmeyi planlamıyorsanız, [platformunuz için Adapty SDK'yı gözlemci modunda yükleyin](implement-observer-mode). Bu aşamada yalnızca SDK'yı projenize eklemeniz, gözlemci modu etkin şekilde başlatmanız ve işlemleri raporlamanız gerekir: Bu kurulum, web'den uygulamaya attribution'ı etkinleştirir: - Kullanıcılar uygulamanızı yüklediğinde, Adapty SDK bağlantı parametrelerinden kurulum ayrıntılarını alır; böylece Adapty Attribution kampanya bilgilerini edinebilir. - Adapty SDK, uygulama içindeki gelirle ilgili tüm olayları bilir ve bunları web kampanyalarına atfedebilir. ## Adım 1. Adapty Attribution'ı Açın \{#step-1-open-adapty-attribution\} :::important **Attribution** Adapty logosuna tıkladığınızda görünmüyorsa, tarayıcı ayarlarınızdan adapty.io için çerezleri ve site verilerini temizleyin, ardından sayfayı yenileyin. ::: Başlıktaki Adapty logosuna tıklayın ve **Attribution** seçeneğini seçin. Abonelik etkinlikleri otomatik olarak Adapty Attribution'a akmaya başlar. Kampanya verileri, 2. Adımda bir veri kaynağı bağladıktan sonra görünür. Olay iletimini duraklatmak için Adapty Kontrol Paneli'nde **Integrations > Adapty** bölümünü açın ve geçişi kapatın. ### Desteklenen olaylar \{#supported-events\} Adapty varsayılan olarak User Acquisition'a üç grup olay gönderir: - Denemeler (Trials) - Abonelikler - Sorunlar (Issues) Desteklenen olayların tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/events-ua.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 2. Reklam platformunuzu bağlayın ve izleme bağlantıları ekleyin \{#step-2-connect-your-ad-platform-and-add-tracking-links\} Adapty, uygulama kurulumlarını kampanya verileriyle eşleştirmek için izleme bağlantıları kullanır. Adapty Attribution ile ölçmek istediğiniz her reklam kampanyasında hedef URL olarak bir izleme bağlantısı kullanmanız gerekir. Birden fazla platformda reklam yayınlıyorsanız, her platform için izleme bağlantılarını ayrı ayrı ayarlayın. Adapty'nin reklam platformlarıyla çalışma biçimi iki şekildedir: - **Yerel entegrasyonlar (Meta Ads, TikTok Ads).** Adapty, reklam platformuna doğrudan bağlanır. Takip bağlantıları otomatik olarak oluşturulur ve kampanya parametreleri, bağlantının kullanıldığı yere göre dinamik olarak doldurulur. Aynı bağlantıyı farklı kampanyalar, reklam grupları veya görseller genelinde kullanabilirsiniz; Adapty, doğru kampanya verilerini ve reklam harcamalarını otomatik olarak alır. - **Yalnızca izleme linkleri (diğer tüm reklam platformları).** Adapty reklam platformuna bağlanmaz. İzleme linkleri manuel olarak oluşturulur ve tüm kampanya parametreleri link oluşturulurken açıkça tanımlanmalıdır. Bu platformlar için reklam harcaması verisi mevcut değildir. <Tabs> <TabItem value="meta" label="Meta Ads" default> Meta Ads için izleme linki oluşturmak üzere: 1. Adapty Attribution Kontrol Paneli'nde [Integrations > Meta](https://app.adapty.io/ua/integrations/facebook/accounts) bölümüne gidin ve **Continue with Facebook** düğmesine tıklayın. 2. Facebook hesabınızla giriş yapın ve **Continue** butonuna tıklayın. 3. İstenen izinleri inceleyin ve **Save** butonuna tıklayın. 4. **Web campaigns** sekmesine geçin ve **Create campaign** butonuna tıklayın. Uygulamayı seçin ve **Save** butonuna tıklayın. 5. **General** sekmesinde **iOS** ve/veya **Android** bölümünü genişletin, App Store ve/veya Google Play uygulama URL'lerini yapıştırın. Ardından **Save** butonuna tıklayın. 6. **Bir bağlantı** veya platforma özel bir bağlantı için **Click link** alanının değerini kopyalayın. Ardından Meta Ads Manager'da reklamınızı açın ve bu bağlantıyı hedef URL olarak yapıştırın. :::important **Website URL** alanına `https://api-ua.adapty.io/api/v1/attribution/click` adresini yapıştırın. Bağlantının geri kalanını **Tracking** bölümündeki **URL parameters** alanına yapıştırın. Bu, Meta reklamınızın onaylanmasına yardımcı olacaktır. [Meta Ads Manager'da reklam oluşturma hakkında daha fazla öneri](meta-create-campaign) için bakabilirsiniz. ::: 7. Meta Ads'te reklamınızı yayınladığınızda, veriler Adapty Attribution kontrol panelinde analiz için kullanılabilir hale gelecektir. </TabItem> <TabItem value="tiktok" label="TikTok for Business"> TikTok for Business için takip bağlantısı oluşturmak amacıyla: 1. Adapty Attribution Kontrol Paneli'nde [Integrations > TikTok Ads](https://app.adapty.io/ua/integrations/tiktok/accounts) bölümüne gidin ve **Continue with TikTok** seçeneğine tıklayın. 2. TikTok hesabınızla giriş yapın ve **Continue** seçeneğine tıklayın. 3. İstenen izinleri inceleyin ve **Save** seçeneğine tıklayın. 4. **Web campaigns** sekmesine geçin ve **Create campaign** butonuna tıklayın. Uygulamayı seçin ve **Save** butonuna tıklayın. 5. **General** sekmesinde **iOS** ve/veya **Android** bölümünü genişletin ve App Store ile/veya Google Play uygulama URL'lerini yapıştırın. Ardından **Save** butonuna tıklayın. 6. **Click link** alanındaki değeri **tek bir link** veya platforma özgü bir link için kopyalayın. Ardından TikTok Ads Manager'da reklamınızı oluştururken bu değeri **Advanced Settings** bölümündeki **Tracking URL** alanına yapıştırın. Bu sayede Adapty, kurulumları ve satın almaları TikTok'taki reklamlarla ilişkilendirebilir. Bkz. [TikTok Ads'te kampanya kurulum rehberi](tiktok-create-campaign). 7. TikTok for Business'ta reklamınızı yayınladığınızda, veriler Adapty Attribution kontrol panelinde analiz için kullanılabilir hale gelecektir. </TabItem> <TabItem value="others" label="Diğer reklam platformları"> Diğer reklam platformları için izleme bağlantısı oluşturmak üzere: 1. Adapty Attribution kontrol panelinde, kenar çubuğu menüsünden **Tracking links** bölümüne gidin. Ardından **Create link** düğmesine tıklayın. 2. Listeden uygulamanızı seçin ve **Next** düğmesine tıklayın. 3. Kampanya ve izlemek istediğiniz reklamla eşleşecek şekilde bağlantı parametrelerini doldurun. 4. Varsayılan olarak bir One Link oluşturursunuz. Bu bağlantı, kullanıcının platformunu otomatik olarak algılar ve tıklamayı izledikten sonra App Store'a veya Google Play'e yönlendirir. Her platform için ayrı yönlendirme URL'leri kullanmak isterseniz **One Link** onay kutusunun işaretini kaldırın ve her platforma özgü mağaza bağlantılarını manuel olarak girin. 5. **Create**'e tıklayın. 6. Takip bağlantısı sayfanızı açın ve bölümlerden birinden **Click link**'i kopyalayın: - **One link** – tıklamaları izlemek ve kullanıcıları otomatik olarak doğru mağazaya yönlendirmek için bu bağlantıyı kullanın. - **iOS link** veya **Android link** — her mağaza için ayrı bağlantı istiyorsanız kullanabileceğiniz isteğe bağlı platforma özgü sürümler. 7. Reklam platformunuza gidin ve bağlantıyı reklamınıza reklam hedef URL'si olarak yapıştırın. </TabItem> </Tabs> ## Adım 3. Web-to-app kampanyanızı başlatın ve sonuçları görüntüleyin \{#step-3-launch-your-web-to-app-campaign-and-view-results\} Kampanyanız yayına girip kullanıcılar uygulamanızı yüklemeye başladığında Adapty, yüklemeleri ve gelirleri kampanyalarınıza atfetmeye başlar. [Adapty UA analitik kontrol panelinde](ua-analytics) şu kampanya düzeyindeki metrikleri görürsünüz: - Yüklemeler ve dönüşümler - Abonelik ve satın alma gelirleri - Reklam platformu, kampanya, reklam seti ve görsel bazında performans dökümü Metrikler, uygulamanızdan yükleme ve gelir olayları alınır alınmaz görünür. Reklam harcaması verileri yalnızca yerel entegrasyona sahip platformlarda kullanılabilir. ## Daha Fazla Bilgi \{#learn-more\} Adapty Attribution analitiği ve büyük reklam platformlarında kampanya yürütmeye yönelik pratik kılavuzlar için ayrıntılı dokümantasyona devam edin: - [**Adapty Attribution'da Analitik**](ua-analytics): Analitik kontrol panelini etkili bir şekilde nasıl kullanacağınızı öğrenin. - [**Adapty Attribution'da Metrikler**](ua-metrics): Kullanıcı edinimi analizi için mevcut metrikleri keşfedin. - [**Entegrasyonlar**](ua-integrations): Adapty Attribution tarafından desteklenen reklam platformlarını ve entegrasyonları inceleyin. - [**Meta Ads Manager'da reklam yayınlama**](meta-create-campaign): Meta Ads Manager'da kampanyaları nasıl kuracağınızı ve başlatacağınızı öğrenin. - [**TikTok for Business'ta reklam yayınlama**](tiktok-create-campaign): TikTok for Business'ta kampanyaları nasıl kuracağınızı ve başlatacağınızı öğrenin. --- # File: ua-metrics --- --- title: "Adapty Attribution'daki Metrikler" description: "Adapty Attribution'da kullanılabilen metrikler hakkında bilgi edinin." --- Adapty Attribution, kampanya performansını ve kullanıcı davranışını ölçmek için kapsamlı **metrikler** sunar. Bu metrikler standart değerler olarak kullanılabilirken, bazı metrikler kullanıcı gruplarının zaman bazlı analizi için **kohort metrikleri** olarak da sunulur. ## Standart metrikler \{#standard-metrics\} | **Metrik** | Açıklama | Kohort | |-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------| | **Spend** | Reklamınızdaki her bir kullanıcı tıklamasının maliyetinin toplamı. | Hayır | | **Impressions** | Seçilen dönemde reklamınızın kaç kez görüntülendiği. | Hayır | | **Clicks** | Raporlama döneminde kullanıcıların reklamınıza kaç kez tıkladığı. | Hayır | | **CPI** | **CPI (Yükleme Başına Maliyet)**, her yükleme için ödediğiniz tutardır. <br/>**Formül**: `Spend / Installs` | Hayır | | **CPC** | **CPC (Tıklama Başına Maliyet)**, reklamınızdaki her tıklama için ödediğiniz tutardır. <br/>**Formül**: `Spend / Clicks` | Hayır | | **CPM** | **CPM (Bin Gösterim Başına Maliyet)**, her bin reklam gösterimi için ödediğiniz tutardır. <br/>**Formül**: `Spend / (Impressions / 1000)` | Hayır | | **ICR** | **ICR (Yükleme Dönüşüm Oranı)**, yüklemeyle sonuçlanan reklam tıklamalarının yüzdesidir. <br/>**Formül**: `(Installs / Clicks) × 100%` | Hayır | | **IPM** | **IPM (Bin Gösterim Başına Yükleme)**, her bin reklam gösteriminde gerçekleşen yükleme sayısını ifade eder. <br/>**Formül**: `(Installs / Impressions) × 1000` | Hayır | | **CTR** | **CTR (Tıklama Oranı)**, tıklamayla sonuçlanan gösterimlerin yüzdesidir. <br/>**Formül**: `(Clicks / Impressions) × 100%` | Hayır | | **Inline link clicks** | Kullanıcıların reklam materyallerinizdeki veya uygulama sayfanızdaki satır içi bağlantılara kaç kez tıkladığı. | Hayır | | **Cost per inline link click** | Her satır içi bağlantı tıklaması için ödediğiniz ortalama tutar. <br/>**Formül**: `Spend / Inline Link Clicks` | Hayır | | **Inline link click CTR** | Satır içi bağlantı tıklamasıyla sonuçlanan gösterimlerin yüzdesi. <br/>**Formül**: `(Inline Link Clicks / Impressions) × 100%` | Hayır | | **Installs** | Raporlama döneminde uygulamanızı yükleyen toplam kullanıcı sayısı (yeniden yüklemeler dahil). | Hayır | | **Revenue** | Seçilen zaman diliminde bu kampanyayla ilişkilendirilen satın alımlardan elde edilen toplam gelir (mağaza komisyonu öncesi). | Evet | | **ROAS** | **ROAS (Reklam Harcamasından Elde Edilen Gelir)**, reklam gelirinizin reklam harcamanıza bölünmesiyle yüzde olarak ifade edilen değerdir. <br/> **Formül**: `Spend > 0 ise (Revenue / Spend) × 100%, aksi hâlde 0%` | Evet | | **ARPU** | **ARPU (Kullanıcı Başına Ortalama Gelir)**, kohortdaki kullanıcı başına düşen ortalama gelirdir. <br/>**Formül**: `Revenue / Users` | Evet | | **LTV** | **LTV (Yaşam Boyu Değer)**, bir kullanıcıya yaşamı boyunca atfedilen ortalama gelirdir. <br/>**Formül**: `Revenue / Installs` | Hayır | | **Cost per trial** | Başlatılan her deneme için ödediğiniz ortalama tutar. <br/>**Formül**: `Spend / Count trial started` | Hayır | | **Cost per subscription** | Satın alınan her abonelik ürünü için ödediğiniz ortalama tutar. <br/>**Formül**: `Spend / Count subscription started` | Hayır | | **Count subscription events** | Raporlama döneminde abonelikle ilgili olayları sayan metrik grubu. Metrikler şunlardır: <br/>- Count subscription started<br/>- Count subscription renewed<br/>- Count subscription renewal cancelled<br/>- Count subscription renewal reactivated<br/>- Count subscription expired<br/>- Count [subscription deferred](https://adapty.io/glossary/subscription-purchase-deferral/)<br/>- Count subscription refunded | Evet | | **Count trial events** | Raporlama döneminde denemeyle ilgili olayları sayan metrik grubu. Metrikler şunlardır: <br/>- Count trial started<br/>- Count trial converted<br/>- Count trial expired<br/>- Count trial renewal reactivated | Evet | | **Count billing issue detected** | Raporlama döneminde tespit edilen fatura sorunlarının sayısı. | Evet | | **Count entered grace period** | Fatura sorunları nedeniyle ek süreye giren aboneliklerin sayısı. | Evet | | **Count non-subscription events** | Raporlama döneminde abonelik dışı olayları sayan metrik grubu. Metrikler şunlardır: <br/>- Count non-subscription purchased<br/>- Count non-subscription refunded | Evet | | **Subscription events rate** | Raporlama döneminde abonelikle ilgili olayların uygulama yüklemelerine oranını gösteren metrikler. Metrikler şunlardır: <br/>- Rate subscription started<br/>- Rate subscription renewed<br/>- Rate subscription renewal cancelled<br/>- Rate subscription renewal reactivated<br/>- Rate subscription expired<br/>- Rate [subscription deferred](https://adapty.io/glossary/subscription-purchase-deferral/)<br/>- Rate subscription refunded | Evet | | **Trial events rate** | Raporlama döneminde denemeyle ilgili olayların uygulama yüklemelerine oranını gösteren metrikler. Metrikler şunlardır: <br/>- Rate trial started<br/>- Rate trial converted<br/>- Rate trial expired<br/>- Rate trial renewal reactivated | Evet | | **Rate billing issue detected** | Raporlama döneminde fatura sorunlarının uygulama yüklemelerine oranı. | Evet | | **Rate entered grace period** | Raporlama döneminde ek süreye giren aboneliklerin uygulama yüklemelerine oranı. | Evet | | **Non-subscription events rate** | Raporlama döneminde abonelik dışı olayların uygulama yüklemelerine oranını gösteren metrikler. Metrikler şunlardır: <br/>- Rate non-subscription purchased<br/>- Rate non-subscription refunded | Evet | ## Tahmin edilen metrikler \{#predicted-metrics\} Tahmin edilen metrikler, bir kohortun gelecekteki performansını uygulamanın kendi geçmiş verilerinden projekte eder. D30, D60, D90, D180 ve D360 gibi birden fazla kohort döneminde kullanılabilir; ayrıca gün bazında özel dönemler de ekleyebilirsiniz. Bu değerlerin nasıl hesaplandığına ilişkin ayrıntılar için bkz. [Adapty Attribution'da tahmin edilen metrikler](ua-predicted-metrics). | **Metrik** | Açıklama | Kohort | |---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------| | **pRevenue** | Bir kohortun hedef ufka kadar üretmesi beklenen toplam tahmin geliri. Uygulamanın geçmiş kohort elde tutma verilerinden modellenir. | Evet | | **pROAS** | Aynı ufuk boyunca reklam harcamasının tahmini getirisi. **Formül**: `(pRevenue / Spend) × 100%` | Evet | | **pAdProfit** | Ufuk boyunca reklam harcaması düşüldükten sonraki tahmini gelir. **Formül**: `pRevenue − Spend` | Evet | | **pARPU** | Ufuk boyunca kurulum başına tahmini ortalama gelir (tahmini LTV). **Formül**: `pRevenue / Installs` | Evet | | **pARPPU** | Ufuk boyunca ödeme yapan kullanıcı başına tahmini ortalama gelir. **Formül**: `pRevenue / paying users at d{N}`, burada `d{N}` seçilen ufukla eşleşir. | Evet | --- # File: ua-predicted-metrics --- --- title: "Adapty Attribution'da Tahmin Edilen Metrikler" description: "Adapty Attribution'da kohortlar için gelir, ROAS, reklam kârı ve LTV tahminleri yapın." --- :::important Bu makale yalnızca Adapty Attribution'daki tahminleri kapsamaktadır. Kohort analizi sayfasındaki tahmini LTV ve gelir için bkz. [Kohortlarda tahminler](predicted-ltv-and-revenue). ::: Adapty Attribution, her kohort için gelecekteki geliri ve birim ekonomisini tahmin eder; böylece kampanyaları olgunlaşmadan önce karşılaştırabilirsiniz. Tahminler, uygulamanın kendi geçmiş kohort verilerinden üretilir ve her gün güncellenir. En çok henüz uzun abonelik döngülerini tamamlamamış yeni kohortları değerlendirmek için kullanışlıdır. ## Tahmin edilen metrikler \{#predicted-metrics\} | **Metrik** | Açıklama | |---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **pRevenue** | Bir kohortun hedef ufka kadar üretmesi beklenen toplam tahmin geliri. Uygulamanın geçmiş kohort elde tutma verilerinden modellenir. | | **pROAS** | Aynı ufuk boyunca reklam harcamalarından tahmini geri dönüş. **Formül**: `(pRevenue / Spend) × 100%` | | **pAdProfit** | Ufuk boyunca reklam harcaması düşüldükten sonra kalan tahmini gelir. **Formül**: `pRevenue − Spend` | | **pARPU** | Ufuk boyunca yükleme başına tahmini ortalama gelir (tahmini LTV). **Formül**: `pRevenue / Installs` | | **pARPPU** | Ufuk boyunca ödeme yapan kullanıcı başına tahmini ortalama gelir. **Formül**: `pRevenue / paying users at d{N}`, burada `d{N}` seçilen ufukla eşleşir. | `pRevenue` temel değerdir. Diğer dört metrik, model ayrı ayrı çalıştırılarak değil, gözlemlenen kohort verileri (harcama, kurulum ve ödeme yapan kullanıcılar) kullanılarak bu değerden türetilir. Tahmin edilen her metrik, birden fazla kohort dönemi için kullanılabilir: D0, D3, D7, D30, D60, D90, D180 ve D360. Özel bir dönem de gün cinsinden ekleyebilirsiniz. Dönem, değerin kohortun kurulum tarihinden itibaren ne kadar ileriye yansıtıldığını tanımlar. ## Tahminler nasıl hesaplanır \{#how-predictions-are-calculated\} Tahminler, her uygulamanın kendi geçmiş kohortlarından oluşturulur. Model, geçmiş kohortların başlangıç günlerinden sonra gelirlerinin nasıl büyüdüğünü ölçer, ardından mevcut kohortu aynı yörüngeyi kullanarak ileriye dönük olarak öngörür. ### Temel gün \{#baseline-day\} Tahminler yalnızca kohort temel gününe ulaştıktan sonra kullanılabilir hale gelir. Temel gün, bir kohortun başlangıç gelirinin %90'ının genellikle elde edildiği ilk gündür. Başlangıç geliri; abonelik başlangıçlarını, deneme sürümü dönüşümlerini ve tek seferlik satın almaları kapsar; yenilemeler bu eşiğe dahil edilmez. Temel gün, uygulamanın deneme süresi uzunluğuna ve ürün karmasına bağlıdır: - **Deneme süresi olmayan uygulamalar**: Temel gün genellikle kurulumdan sonraki ilk birkaç gün içine düşer. - **Kısa deneme süresi olan uygulamalar**: Temel gün, genellikle deneme süresi dönüşümünden kısa süre sonra oluşur. - **Uzun deneme süresi olan uygulamalar**: Temel gün, kurulumdan bir hafta veya daha sonrasına denk gelebilir; çünkü ilk gelirin büyük kısmı ancak deneme süresi tamamlandıktan sonra gerçekleşir. ### Abonelik türüne göre projeksiyon \{#projection-by-subscription-type\} Başlangıç gününde, kohortun ilk geliri beş kategoriye ayrılır: aylık, yıllık, haftalık ve üç aylık abonelikler ile tek seferlik satın almalar. Her kategori, uygulamanın geçmiş kohortlarından ölçülen bir yörünge kullanılarak bağımsız olarak ileriye dönük tahmin edilir. Model, daha yakın tarihli kohortlara ve işlem başına benzer gelir ile benzer ürün karışımı gibi karşılaştırılabilir ekonomik özelliklere sahip kohortlara daha fazla ağırlık verir. Dolayısıyla bir tahmin, uygulamadaki en güncel ve en benzer kohortların gerçekte nasıl performans gösterdiğini yansıtır. ## Tahminler ne zaman kullanılabilir \{#when-predictions-are-available\} Bir tahmin, yalnızca kohort bunu destekleyecek kadar veriye sahipse gösterilir. Değer üretilemediğinde sütunda em-tire (`—`) gösterilir. Tahminin kullanılamadığı yaygın nedenler: - **Kohort, temel gününe ulaşmadı**: Modelin ileriye dönük projeksiyon yapabilmesi için kohortun başlangıç gelirinin stabilize olması gerekir. - **Uygulama için yeterli geçmiş veri yok**: Uygulamada ilgili abonelik türüne ait yeterli sayıda geçmiş kohort yoksa model, güvenilir elde tutma oranlarını hesaplayamaz. Tahminler, en güncel işlem verileriyle her gün yeniden hesaplanır; bu nedenle aynı kohort için değerler, daha fazla gelir gözlemlendikçe değişebilir. --- # File: ua-tracking-links --- --- title: "Adapty Attribution'da İzleme Bağlantıları" description: "Kampanyalarınızı takip edin ve başarılarını her yerde ölçün." --- Takip bağlantıları, kullanıcılarınızın nereden geldiğini ölçmenize ve kurulumları reklam kampanyalarıyla ilişkilendirmenize yarar. Biri reklamınıza tıkladığında Adapty bu tıklamayı kaydeder ve daha sonra SDK tarafından gönderilen kurulum olayıyla eşleştirir. Böylece hangi kanalların, kampanyaların, reklam setlerinin ve reklamların [Analiz sayfanızda](ua-analytics) en fazla gelir getirdiğini görebilirsiniz. İki tür takip bağlantısı oluşturabilirsiniz: - **One link** — kullanıcının platformunu otomatik olarak algılayan, tıklamayı kaydeden ve kişiyi App Store veya Google Play'e yönlendiren evrensel bir bağlantı. - **Mağazaya özel bağlantılar** — hem tıklamayı kaydeden hem de kullanıcıları App Store veya Google Play'e otomatik olarak yönlendiren platforma özgü bağlantılar. Bu bağlantılara ertelenmiş deep link parametreleri de ekleyebilirsiniz. ## İzleme bağlantıları oluşturma \{#create-tracking-links\} İzleme bağlantısı oluşturmak için: 1. Adapty Attribution kontrol panelinde, yan menüden **Tracking links** seçeneğine gidin. Ardından **Create link** düğmesine tıklayın. 2. Listeden uygulamanızı seçin ve **Next** düğmesine tıklayın. 3. Bağlantı parametrelerini, takip etmek istediğiniz kampanya ve reklamla eşleşecek şekilde doldurun. | Parametre | Açıklama | |-------------------|-----------------------------------------------------------------------------------------------| | **Name** | Takip bağlantısının dahili adı. | | **Channel** | Meta, Reddit veya TikTok gibi trafik kaynağı. Analizlerde kampanyaları gruplamak için kullanılır. | | **Campaign ID** | Reklam platformunuzdaki kampanyanın benzersiz tanımlayıcısı. | | **Campaign name** | Kampanyanın okunabilir adı. | | **Ad set ID** | Reklam platformunuzdaki reklam setinin (reklam grubu) benzersiz tanımlayıcısı. | | **Ad set name** | Reklam setinin adı. | | **Ad ID** | Bireysel reklam öğesinin benzersiz tanımlayıcısı. | | **Ad name** | Reklam öğesinin veya varyasyonunun adı. | 4. Varsayılan olarak bir One Link oluşturursunuz. Bu bağlantı, kullanıcının platformunu otomatik olarak algılar ve tıklamayı kaydettikten sonra kişiyi App Store veya Google Play'e yönlendirir. Her platform için ayrı yönlendirme URL'leri kullanmak isterseniz **One Link** onay kutusunun işaretini kaldırın ve platforma özgü mağaza bağlantılarını manuel olarak girin. 5. **Create** butonuna tıklayın. 6. Takip bağlantısı sayfanızı açın ve aşağıdaki bölümlerden birindeki **Click link**'i kopyalayın: - **One link** — tıklamaları takip etmek ve kullanıcıları doğru mağazaya otomatik olarak yönlendirmek için bu bağlantıyı kullanın. - **iOS link** veya **Android link** — her mağaza için ayrı bağlantı istiyorsanız kullanabileceğiniz isteğe bağlı platforma özgü sürümler. :::tip [Ertelenmiş verilerle çalışmak](ua-deferred-data) için ek bağlantı parametreleri de ayarlayabilirsiniz. Örneğin ertelenmiş deep linking uygulayabilirsiniz. ::: 7. Reklam platformunuza gidin ve bağlantıyı reklam hedef URL'si olarak reklamınıza yapıştırın. Artık uygulama kurulumları, geldikleri reklam ve kampanyalarla eşleştirilecek; böylece **Analytics** sayfasında kampanya etkinliğini ölçebileceksiniz. --- # File: ua-deferred-data --- --- title: "Adapty Attribution'da Ertelenmiş Deeplinkler" description: "Adapty Attribution'da ertelenmiş deeplinkleri ayarlayın." --- Ertelenmiş deeplink'ler, kullanıcılar reklamlarınıza tıkladıktan sonra uygulamanızı yüklediğinde özel verileri uygulamanıza aktarmanızı sağlar. Örneğin, kullanıcılar uygulamayı yükleyip ilk kez açar açmaz onları uygulamanızdaki belirli bir konuma yönlendirebilirsiniz. İşleyiş şekli şöyledir: 1. Kullanıcı reklamınıza tıkladığında Adapty, tıklama verilerini kaydeder. 2. Adapty, yükleme olayını kaydettiğinde tıklamaya ait ertelenmiş verileri alır. 3. Kullanıcı uygulamanızı yükleyip ilk kez başlattığında Adapty, depolanan verileri getirir ve uygulamanız özel parametreleri alır; böylece uygulama kodunuzda farklı değerlere göre tepki verebilirsiniz. Adapty aşağıdaki ertelenmiş veri parametrelerini destekler: - `ios_deferred_data` - `android_deferred_data` - `deferred_data_sub[1-10]` Ertelenmiş veri parametrelerini eklemek için bunları kampanya ayarlarınızdaki linke ekleyin: 1. **Integrations -> Meta/TikTok Ads** sayfasından kampanyanızı açın. Ya da **Tracking links** sayfasından takip linkinizi açın. Kampanyanızda kullanacağınız tıklama linkini kopyalayın. 2. Reklam platformunuzda (Meta, TikTok, Google Ads vb.) bu bağlantıyı reklam hedef URL alanına yapıştırın, ardından ertelenmiş veri parametrelerini ekstra sorgu parametreleri olarak ekleyin — her biri `&` önekiyle başlayacak şekilde. Örneğin, iOS kullanıcılarını yükleme sonrasında bir 'Welcome' ekranına göndermek için `&ios_deferred_data=welcome` ekleyin. Nihai hedef URL şuna benzer: ``` https://api-ua.adapty.io/api/v1/attribution/click?adpt_cid=__ADAPTY__ID__&ios_deferred_data=welcome&campaign_id=__CAMPAIGN_ID__&adset_id=__AID__&ad_id=__CID__&campaign_name=__CAMPAIGN_NAME__&adset_name=__AID_NAME__&ad_name=__CID_NAME__&redirect_url=__APP_LINK__ ``` 3. Uygulama kodunuzda parametrelere yanıt verin. Ertelenmiş veri parametrelerinin `payload` parametresi içinde yer aldığını ve `payload` parametresinin kaçışlı bir JSON olduğunu unutmayın; bu nedenle uygulama kodunuzda parse etmeniz gerekir. Örneğin, `ios_deferred_data` değerinin `welcome` olduğu kurulumları şu şekilde ele alabilirsiniz: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers Adapty.delegate = self nonisolated func onInstallationDetailsSuccess(_ details: AdaptyInstallationDetails) { guard let payloadStr = details.payload, let data = payloadStr.data(using: .utf8), let payload = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let deeplink = payload["ios_deferred_data"] as? String, deeplink == "welcome" else { return } DispatchQueue.main.async { print("Navigate to welcome screen") // navigate to your screen here } } ``` </TabItem> <TabItem value="android" label="Kotlin"> ```kotlin showLineNumbers Adapty.setOnInstallationDetailsListener(object : OnInstallationDetailsListener { override fun onInstallationDetailsSuccess(details: AdaptyInstallationDetails) { details.payload?.let { runCatching { val json = JSONObject(it) if (json.optString("android_deferred_data") == "welcome") { println("Navigate to welcome screen") // navigate here } }.onFailure(Throwable::printStackTrace) } } }) ``` </TabItem> <TabItem value="rn" label="React Native" default> ```typescript showLineNumbers adapty.addEventListener('onInstallationDetailsSuccess', details => { // Parse the payload JSON and navigate to welcome screen if needed try { if (details.payload) { const payload = JSON.parse(details.payload); if (payload.ios_deferred_data === 'welcome') { // Navigate to welcome screen // Replace with your app's navigation logic // For example, using React Navigation: // navigation.navigate('Welcome'); console.log('Navigate to welcome screen'); } } } catch (error) { console.error('Error parsing installation details payload:', error); } }); ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers Adapty().onUpdateInstallationDetailsSuccessStream.listen((details) { final payloadStr = details.payload; if (payloadStr == null) return; final payload = json.decode(payloadStr) as Map<String, dynamic>; if (payload['ios_deferred_data'] == 'welcome') { print('Navigate to welcome screen'); } }); ``` </TabItem> </Tabs> --- # File: ua-attribution-data --- --- title: "Uygulamanızda attribution verilerini alın" description: "Adapty bir kurulumu bir kampanyayla eşleştirdikten sonra uygulamanızdaki kampanya attribution verilerine erişin." --- Adapty bir kurulumu bir kampanyayla eşleştirdiğinde, `onInstallationDetailsSuccess` callback'i aracılığıyla uygulamanıza attribution verisi döndürür. Bu veriyi, kurulumu sağlayan kanal veya kampanyaya göre kullanıcı deneyimini kişiselleştirmek için kullanabilirsiniz. Attribution verisi, `payload` alanının içindeki iç içe geçmiş bir `attribution` nesnesi olarak döndürülür. Aşağıdaki alanları içerir: | Alan | Açıklama | |---|---| | `channel` | Edinim kanalı (ör. `facebook`, `tiktok`, `google`, `organic`) | | `campaign_id` | Kampanya tanımlayıcısı | | `campaign_name` | Kampanya adı | | `adset_id` | Reklam seti / reklam grubu tanımlayıcısı | | `adset_name` | Reklam seti / reklam grubu adı | | `ad_id` | Reklam / kreatif tanımlayıcısı | | `ad_name` | Reklam / kreatif adı | Tüm alanlar isteğe bağlıdır. Organik kurulumlar veya attribution belirlenemediği durumlarda `payload` alanı `attribution` nesnesini içermez. Uygulamanızda attribution verilerini okumak için: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers Adapty.delegate = self nonisolated func onInstallationDetailsSuccess(_ details: AdaptyInstallationDetails) { guard let payloadDict = details.payload?.dictionary, let attribution = payloadDict["attribution"] as? [String: Any] else { return } let channel = attribution["channel"] as? String let campaignName = attribution["campaign_name"] as? String let adName = attribution["ad_name"] as? String print("Channel: \(channel ?? "organic")") } ``` </TabItem> <TabItem value="android" label="Kotlin"> ```kotlin showLineNumbers Adapty.setOnInstallationDetailsListener(object : OnInstallationDetailsListener { override fun onInstallationDetailsSuccess(details: AdaptyInstallationDetails) { val payloadStr = details.payload ?: return runCatching { val payload = JSONObject(payloadStr) val attribution = payload.optJSONObject("attribution") ?: return val channel = attribution.optString("channel") val campaignName = attribution.optString("campaign_name") val adName = attribution.optString("ad_name") println("Channel: $channel") }.onFailure(Throwable::printStackTrace) } }) ``` </TabItem> <TabItem value="rn" label="React Native"> ```typescript showLineNumbers adapty.addEventListener('onInstallationDetailsSuccess', details => { try { if (!details.payload) return; const payload = JSON.parse(details.payload); const attribution = payload.attribution; if (!attribution) return; const channel = attribution.channel; const campaignName = attribution.campaign_name; const adName = attribution.ad_name; console.log('Channel:', channel ?? 'organic'); } catch (error) { console.error('Error parsing payload:', error); } }); ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers Adapty().onUpdateInstallationDetailsSuccessStream.listen((details) { final payloadStr = details.payload; if (payloadStr == null) return; final payload = json.decode(payloadStr) as Map<String, dynamic>; final attribution = payload['attribution'] as Map<String, dynamic>?; if (attribution == null) return; final channel = attribution['channel'] as String?; final campaignName = attribution['campaign_name'] as String?; final adName = attribution['ad_name'] as String?; print('Channel: ${channel ?? 'organic'}'); }); ``` </TabItem> </Tabs> --- # File: ua-facebook --- --- title: "Meta Ads'i Adapty Attribution ile Entegre Edin" description: "Meta Ads'i Adapty Attribution'a bağlayarak Facebook, Instagram, Messenger ve Audience Network'teki kampanya performansını takip edin ve optimize edin." --- Adapty Attribution'ın Meta entegrasyonu, Facebook, Instagram, Messenger ve Audience Network genelinde kampanya performansını takip etmenizi ve optimize etmenizi sağlar. :::tip [Meta Ads Manager'da reklam kurulumu rehberimize](meta-create-campaign) göz atın. ::: ## Adım 1. Facebook hesabınızı bağlayın \{#step-1-connect-your-facebook-account\} Meta Ads'i Adapty Attribution'a bağlamak için sol kenar çubuğundan **Integrations > Meta** bölümüne gidin. İki seçeneğiniz var: - **Continue with Facebook**: OAuth üzerinden bağlanır. Meta Ads Manager'a kişisel veya iş Facebook hesabınızla giriş yapıyorsanız bunu kullanın. - **Add system token**: Kalıcı bir sistem kullanıcı token'ı kullanarak bağlanır. Kuruluşunuz reklam hesaplarını Meta Business sistem kullanıcısı üzerinden yönetiyorsa bunu kullanın. <Tabs> <TabItem value="oauth" label="Continue with Facebook"> :::important Facebook hesabınızın ihtiyaç duyduğunuz kampanyalara ve piksellere erişimi olduğundan emin olun. ::: 1. **Continue with Facebook**'a tıklayın. 2. Facebook hesabınızla giriş yapın ve **Continue**'ya tıklayın. 3. İstenen izinleri gözden geçirin ve **Save**'e tıklayın. </TabItem> <TabItem value="system" label="Add system token"> [Meta Business Settings](https://business.facebook.com/settings/system-users) sayfasında bir [sistem kullanıcısı erişim token'ı](https://developers.facebook.com/documentation/ads-commerce/marketing-api/collaborative-ads/managed-partner-ads/api-guide/prerequisites/generate-access-token-system-user) oluşturun, ardından bunu Adapty Attribution'a ekleyin. :::important Başlamadan önce, Meta Business portföyünüzde takip etmek istediğiniz reklam hesapları atanmış bir [sistem kullanıcısına](https://www.facebook.com/business/help/503306463479099) ihtiyacınız vardır. Ayrıca portföye eklenmiş bir uygulamanız olması gerekir — token oluştururken bu uygulamayı seçersiniz. ::: **Meta Business Settings'te token oluşturun:** 1. **Business Settings** sayfasına gidin. 2. **Users** altında **System users** seçeneğini seçin. 3. Sistem kullanıcınızı seçin, ardından **Generate new token** düğmesine tıklayın. 4. Açılır listeden uygulamanızı seçin. 5. İzin listesinde `ads_read` seçeneğini etkinleştirin. Adapty Attribution'ın kampanya ve reklam verilerinizi okumak için ihtiyaç duyduğu tek izin budur. 6. **Generate token** düğmesine tıklayın. 7. Token'ı kopyalayın ve güvenli bir yerde saklayın. Meta bunu yalnızca bir kez gösterir. :::note **Token expiration** ayarı, bağlantının ne kadar süre aktif kalacağını kontrol eder. Son kullanma tarihi olan bir token, süresi dolmadan önce yeniden oluşturulup yeniden bağlanmalıdır; aksi hâlde attribution durur. Son kullanma tarihi olmayan bir token bunu önler, ancak uzun ömürlü bir kimlik bilgisidir. Güvenli bir şekilde saklayın ve herhangi bir şekilde açığa çıkarsa iptal edin. ::: **Adapty Attribution'da token'ı ekleyin:** 1. **Add system token** seçeneğine tıklayın. 2. Token'ı yapıştırın ve **Connect** seçeneğine tıklayın. </TabItem> </Tabs> Bundan sonra tüm reklam hesaplarınız Adapty Attribution'a eklenecektir. Kampanya eklemeye devam edebilirsiniz. ## Adım 2. Kampanya ekleme \{#step-2-add-campaigns\} Meta kampanyasını Adapty Attribution'a eklemek ve Meta reklamlarınızın Adapty'de nasıl çalıştığını takip etmek için: 1. **Web Campaigns** sekmesine geçin ve **Create configuration** düğmesine tıklayın. 2. **General** sekmesinde **iOS** ve/veya **Android** bölümünü genişletin ve App Store ile/veya Google Play uygulama URL'lerini yapıştırın. 3. **Click link** alanındaki değeri kopyalayın. Ardından Meta Ads Manager'da reklamınızı açın ve bu bağlantıyı yapıştırın. Bu sayede Adapty, yüklemeleri ve satın almaları Meta'daki reklamlara bağlayabilecektir. 4. Dönüşüm etkinliklerini Meta'ya geri göndermek için Meta'daki piksellerinizi Adapty Attribution'daki kampanyalarla ilişkilendirebilirsiniz. Bunun için **Pixel** açılır menüsünden mevcut piksellerinizden birini seçin. Bir piksel seçtikten sonra bağlantıyı doğrulamak için **Send test event** butonuna tıklayabilirsiniz. ## Adım 3. Olayları eşleyin \{#step-3-map-events\} Kampanya optimizasyonu için dönüşüm olaylarını Meta'ya geri göndermek istiyorsanız **Events names** bölümünde olay eşlemesini yapılandırmanız gerekir. Bu sayede kullanıcılar uygulamanızda işlem gerçekleştirdiğinde Adapty, abonelik olaylarını otomatik olarak Meta pikselinize gönderir. **Events names** bölümünde Meta Ads Manager'da izlemek istediğiniz olayları açın. Etkinleştirilen her olay için açılır menüden ilgili Meta olayını seçin ya da özel bir olay belirleyin. Adapty varsayılan olarak Adapty olaylarını Meta'nın standart olaylarıyla eşler. Olay eşleme yapılandırmanızı uygulamak için **Save**'e tıklayın. ## Ek yapılandırma \{#additional-configuration\} ### Ek parametreler \{#additional-parameters\} **Additional parameter** alanı, Adapty dışındaki analizler için özel veri noktaları eklemenizi sağlar. Bu, belirli kampanya veya kullanıcı verilerini harici analitik araçlara ya da attribution iş ortaklarına aktarmanız gerektiğinde kullanışlıdır. **Additional parameter** alanına attribution takibinize dahil etmek istediğiniz özel verileri girin. Ek parametre, Meta'ya gönderilen tüm attribution verilerine dahil edilir ve gelişmiş kampanya analizi ile optimizasyonu için kullanılabilir. Örneğin, aynı kampanyanın birden fazla varyasyonunu yürütüyorsanız, farklı kreatif yaklaşımları birbirinden ayırt etmek için `variant=A` veya `variant=B` ekleyebilirsiniz. :::important Ek parametreler, Meta Ads Manager'a yapıştırdığınız **Click link**'i değiştirir. Bu bağlantıyı oraya zaten kopyaladıysanız ve daha sonra özel bir parametre eklediyseniz, özel parametreyi içeren güncellenmiş tıklama bağlantısını kopyalayıp yapıştırdığınızdan emin olun. ::: <br/> ### Ayarlar \{#settings\} **Settings** sekmesi, Adapty'nin kullanıcı eylemlerini Meta Ads kampanyalarınızla nasıl eşleştireceğini kontrol eder. Bu ayarlar, hem belirleyici hem de olasılıksal attribution eşleştirme için zaman pencerelerini belirler. Yapılandırmak için kampanya ayarlarınızdaki **Settings** sekmesine gidin. Burada ayarlamanız gereken iki ana ayar bulacaksınız: - **Deterministik eşleşme penceresi**: Bu, kullanıcıları kampanyalarla yüksek doğrulukla eşleştirmek için kesin cihaz tanımlayıcılarını (iOS'ta IDFA veya Android'de Advertising ID gibi) kullanır. Maksimum attribution doğruluğu için bunu 168 saat (7 gün) olarak ayarlayın; bu varsayılan ve önerilen değerdir. Bir kullanıcı Meta reklamınıza tıklayıp uygulamanızı bu pencere içinde yüklediğinde, Adapty yüklemeyi cihaz tanımlayıcılarını kullanarak o belirli reklam tıklamasına kesin olarak atfedebilir. - **Probabilistic matching window**: Bu, deterministik eşleştirme mümkün olmadığında kullanıcıları eşleştirmek için istatistiksel modelleme ve cihaz parmak izi kullanır. Çoğu kampanya için bunu 6 saate ayarlayın; bu varsayılan değerdir ve çoğu kullanım senaryosunda iyi çalışır. Yüksek tıklama hacmine sahip kampanyalarda bunu 1-2 saate düşürebilirsiniz. Deterministik olarak eşleştirilemeyen kullanıcılar için (gizlilik ayarları veya diğer faktörler nedeniyle) Adapty, bu daha kısa pencere içinde olasılıksal eşleştirme kullanır. Ayarlarınızı uygulamak için **Save**'e tıklayın. ### Gelir geçersiz kılma \{#revenue-override\} Deneme olaylarını izliyorsanız ve Meta'nın bu olaylara gelir atfetmesini istiyorsanız **Revenue override** bölümünü kullanın. Bu bölüm, **Trial started** olayı etkinleştirildiğinde görünür. Her deneme olayı hedefi için abonelik fiyatının yüzde kaçının gelir olarak raporlanacağını ayarlayın. Örneğin %30 olarak ayarlandığında Adapty, deneme olayları için dönüşüm değeri olarak abonelik fiyatının %30'unu gönderir. Geçersiz kılma eklemek için: 1. **Events names** bölümünde **Trial started**'ı etkinleştirin. 2. **Revenue override**'da **Add override**'a tıklayın. 3. Hedef olayı seçin ve bir gelir yüzdesi girin (0–100). 4. **Save**'e tıklayın. ### Tüm etkinlikleri gönder \{#send-all-events\} Adapty, varsayılan olarak yalnızca bir Meta kampanyasına atfedilen kullanıcılar için pixelinize etkinlik gönderir. Organik ve atfedilmemiş kullanıcılardan gelen etkinlikleri de pixelinize iletmek için **Send all events** seçeneğini etkinleştirin. Bu seçenek etkinleştirildiğinde, kampanya attribution'ından bağımsız olarak her yükleme ve işlem etkinliği pixele gönderilir. Meta'ya kitle modelleme ve kampanya optimizasyonu için daha geniş dönüşüm verisi sağlamak amacıyla bu seçeneği kullanın. Bu seçeneği etkinleştirmek için kampanya ayarlarında **Send all events (forward organic/non-attributed events to this pixel)** seçeneğini işaretleyin ve **Save** düğmesine tıklayın. --- # File: ua-tiktok --- --- title: "TikTok for Business'i Adapty Attribution ile Entegre Edin" description: "TikTok için İşletme'yi Adapty Attribution'a bağlayarak TikTok Ads Manager'da kampanya performansını takip edin ve optimize edin." --- Adapty Attribution'ın TikTok for Business entegrasyonu, TikTok'taki kampanya performansınızı takip etmenizi ve optimize etmenizi sağlar. :::tip [TikTok for Business'ta reklam kurulumu rehberimize](tiktok-create-campaign) göz atın. ::: ## Adım 1. TikTok hesabınızı bağlayın \{#step-1-connect-your-tiktok-account\} 1. Sol kenar çubuğundan **Integrations > TikTok Ads** bölümüne gidin ve **Continue with TikTok** butonuna tıklayın. 2. TikTok hesabınızla oturum açın ve **Continue** butonuna tıklayın. 3. İstenen izinleri inceleyin ve **Save** butonuna tıklayın. Bu işlemin ardından tüm reklam hesaplarınız Adapty Attribution'a eklenecektir. Kampanya eklemeye devam edebilirsiniz. ## 2. Adım. Kampanya ekleme \{#step-2-add-campaigns\} Adapty Attribution'a TikTok for Business kampanyası eklemek ve TikTok reklamlarınızın Adapty'de nasıl çalıştığını takip etmek için: 1. **Web Campaigns** sekmesine geçin ve **Create configuration** butonuna tıklayın. 2. **General** sekmesinde **iOS** ve/veya **Android** bölümünü genişletin ve App Store ile/veya Google Play uygulama URL'lerini yapıştırın. 3. **Click link** alanındaki değeri kopyalayın. Ardından TikTok Ads Manager'da reklamınızı oluştururken bu değeri **Advanced Settings** bölümündeki **Tracking URL** alanına yapıştırın. Bu sayede Adapty, yüklemeleri ve satın almaları TikTok reklamlarıyla ilişkilendirebilir. 4. (İsteğe bağlı) Dönüşüm olaylarını TikTok'a geri göndermek için TikTok'taki piksellerinizi Adapty Attribution'daki kampanyalarla ilişkilendirebilirsiniz. Bunun için **Pixel** açılır menüsünden mevcut piksellerinizden birini seçin. Bir piksel seçtikten sonra bağlantıyı doğrulamak için **Send test event** butonuna tıklayabilirsiniz. ## Adım 3. Etkinlikleri eşleyin \{#step-3-map-events\} Kampanya optimizasyonu için dönüşüm etkinliklerini TikTok'a geri göndermek amacıyla **Events names** bölümünde etkinlik eşlemesini yapılandırmanız gerekir. Bu sayede kullanıcılar uygulamanızda işlem gerçekleştirdiğinde Adapty, abonelik etkinliklerini otomatik olarak TikTok pikseline gönderir. **Events names** bölümünde TikTok Ads Manager'da izlemek istediğiniz etkinlikleri açın. Etkinleştirilen her etkinlik için açılır menüden ilgili TikTok etkinliğini seçin ya da özel bir etkinlik tanımlayın. Adapty, varsayılan olarak Adapty etkinliklerini TikTok'un standart etkinlikleriyle eşler. Etkinlik eşleme yapılandırmanızı kaydetmek için **Save** butonuna tıklayın. ## Ek yapılandırma \{#additional-configuration\} ### Ek parametreler \{#additional-parameters\} **Additional parameter** alanı, Adapty dışındaki analizler için özel veri noktaları eklemenizi sağlar. Bu özellik, belirli kampanya veya kullanıcı verilerini harici analiz araçlarına ya da attribution iş ortaklarına iletmeniz gerektiğinde kullanışlıdır. **Additional parameter** alanına, attribution takibinize dahil etmek istediğiniz özel verileri girin. Ek parametre, TikTok'a gönderilen tüm attribution verilerine dahil edilir ve gelişmiş kampanya analizi ile optimizasyonu için kullanılabilir. Örneğin, aynı kampanyanın birden fazla varyasyonunu yürütüyorsanız, farklı kreatif yaklaşımları birbirinden ayırt etmek için `variant=A` veya `variant=B` ekleyebilirsiniz. :::important Ek parametreler, TikTok Ads Manager'a yapıştırdığınız **Click link**'i değiştirir. Bu bağlantıyı oraya zaten kopyaladıysanız ve daha sonra özel bir parametre eklediyseniz, özel parametreyi içeren güncel click link'i kopyalayıp yapıştırdığınızdan emin olun. ::: <br/> ### Ayarlar \{#settings\} **Settings** sekmesi, Adapty'nin kullanıcı eylemlerini TikTok Ads kampanyalarınızla nasıl eşleştireceğini kontrol eder. Bu ayarlar, hem deterministik hem de olasılıksal attribution eşleştirme için zaman pencerelerini belirler. Yapılandırmak için kampanya yapılandırmanızdaki **Settings** sekmesine gidin. Burada ayarlamanız gereken iki ana ayar bulunur: - **Deterministik eşleşme penceresi**: Bu, kullanıcıları kampanyalarla yüksek hassasiyette eşleştirmek için kesin cihaz tanımlayıcılarını (iOS'ta IDFA veya Android'de Advertising ID gibi) kullanır. Maksimum attribution doğruluğu için bunu 168 saat (7 gün) olarak ayarlayın; bu varsayılan ve önerilen değerdir. Bir kullanıcı TikTok reklamınıza tıklayıp bu süre içinde uygulamanızı yüklediğinde, Adapty yüklemeyi cihaz tanımlayıcılarını kullanarak o belirli reklam tıklamasına kesin olarak atfedebilir. - **Probabilistic matching window**: Bu, deterministik eşleşmenin mümkün olmadığı durumlarda kullanıcıları eşleştirmek için istatistiksel modelleme ve cihaz parmak izi kullanır. Çoğu kampanya için bunu 6 saate ayarlayın; bu varsayılan değerdir ve çoğu kullanım senaryosunda iyi çalışır. Yüksek tıklama hacmine sahip kampanyalar için 1-2 saate düşürebilirsiniz. Deterministik olarak eşleştirilemeyen kullanıcılar için (gizlilik ayarları veya diğer faktörler nedeniyle) Adapty, bu daha kısa zaman penceresi içinde probabilistik eşleşme kullanır. Ayarlarınızı uygulamak için **Save**'e tıklayın. ### Gelir geçersiz kılma \{#revenue-override\} Deneme etkinliklerini izliyorsanız ve TikTok'un bu etkinliklere gelir atfetmesini istiyorsanız **Revenue override** bölümünü kullanın. Bu bölüm, **Trial started** etkinliği etkinleştirildiğinde görünür. Her deneme etkinliği hedefi için abonelik fiyatının yüzde kaçının gelir olarak raporlanacağını belirleyin. Örneğin %30 olarak ayarlandığında Adapty, deneme etkinlikleri için dönüşüm değeri olarak abonelik fiyatının %30'unu gönderir. Geçersiz kılma eklemek için: 1. **Events names** bölümünde **Trial started** etkinliğini etkinleştirin. 2. **Revenue override** bölümünde **Add override** butonuna tıklayın. 3. Hedef etkinliği seçin ve bir gelir yüzdesi (0–100) girin. 4. **Save** butonuna tıklayın. ### Tüm etkinlikleri gönder \{#send-all-events\} Adapty, varsayılan olarak yalnızca bir TikTok kampanyasına atfedilen kullanıcıların etkinliklerini pikselinize gönderir. **Send all events** seçeneğini etkinleştirerek organik ve atfedilmemiş kullanıcıların etkinliklerini de piksele iletebilirsiniz. Bu seçenek etkinleştirildiğinde, kampanya attribution'ından bağımsız olarak her yükleme ve işlem etkinliği piksele gönderilir. TikTok'a kitle modelleme ve kampanya optimizasyonu için daha kapsamlı dönüşüm verisi sağlamak amacıyla bu seçeneği kullanabilirsiniz. Bu seçeneği etkinleştirmek için kampanya ayarlarında **Send all events (forward organic/non-attributed events to this pixel)** seçeneğini işaretleyin ve **Save** düğmesine tıklayın. --- # File: ua-funnelfox --- --- title: "FunnelFox'u Adapty Attribution ile Entegre Edin" description: "FunnelFox web-to-app funnel'larını Adapty Attribution'a bağlayarak web dokunma noktasından ödeme yapan aboneye kadar tam edinme yolunu takip edin." --- [FunnelFox](https://funnelfox.com), kullanıcıları App Store dışında edinmenizi ve ücretlendirmenizi sağlayan — böylece App Store ücretini ve diğer kısıtlamaları atlayan — bir web2app funnel oluşturma platformudur. Bağlantı kurulduğunda, FunnelFox işlem olaylarını Adapty Attribution'a göndererek web dokunma noktasından ödeme yapan aboneye kadar eksiksiz bir attribution yolu oluşturur. Entegrasyonu kurmak için bir **Project ID** kullanarak bir veya daha fazla FunnelFox projesini Adapty uygulamanıza bağlayın. ## Nasıl çalışır \{#how-it-works\} Bir kullanıcı FunnelFox funnelında satın alma işlemini tamamladığında, FunnelFox işlem olayını Adapty Attribution'a gönderir. Adapty, işlemin hangi uygulamaya ait olduğunu belirlemek için **Project ID**'yi kullanır. Olay daha sonra depolanır ve Adapty Attribution analizlerinizde görünür. Her işlem şunları içerir: - **Abonelik yaşam döngüsü olayı**: başlatıldı, yenilendi, iptal edildi, deneme süresi dönüştürüldü, iade edildi ve daha fazlası - **Attribution verisi**: kampanya, reklam seti ve reklam tanımlayıcıları; UTM parametreleri; platform tıklama kimlikleri (fbclid, ttclid, gclid) - **Funnel ve deney verisi**: A/B testi varyantlarını karşılaştırabilmeniz için FunnelFox funnel adı ve deney adı Adapty, işlemdeki tıklama kimliğinden **kanalı** (Facebook, TikTok, Google veya organik) otomatik olarak belirler. Bunu manuel olarak yapılandırmanıza gerek yoktur. :::note FunnelFox işlemleri, web satın almalarında uygulama yükleme olayı bulunmadığından kohort tarihi olarak yükleme tarihi yerine **ilk ödeme tarihini** kullanır. ::: ## Entegrasyonu yapılandırma \{#configure-integration\} ### Adım 1. FunnelFox'ta Project ID'nizi alın \{#step-1-get-your-project-id-in-funnelfox\} 1. FunnelFox kontrol panelinizde sol kenar çubuğundaki **Settings** seçeneğine tıklayın. 2. **Project info** bölümünde **ID** değerini kopyalayın. ### Adım 2. Projeyi Adapty Attribution'a Ekleyin \{#step-2-add-the-project-in-adapty-attribution\} 1. Adapty Attribution'da [**Integrations > FunnelFox**](https://app.adapty.io/ua/integrations/funnelfox) bölümüne gidin. 2. FunnelFox'tan kopyaladığınız Project ID'yi yapıştırın. 3. **Save** butonuna tıklayın. Ek FunnelFox projeleri bağlamak için **Add project** butonuna tıklayın ve her ek proje için her iki adımı tekrarlayın. --- # File: ua-custom-s3 --- --- title: "Adapty Attribution'da Özel S3" description: "Gelişmiş analitik ve raporlama için kullanıcı edinme verilerini özel S3 uyumlu depolama alanınıza aktarın." --- Adapty Attribution'ın özel S3 uyumlu depolama entegrasyonu, kullanıcı edinimi kampanya verilerinizi kendi S3 uyumlu depolama çözümünüzde güvenli bir şekilde saklamanıza olanak tanır. Kampanya performans verilerinizi, attribution verilerinizi ve kullanıcı edinimi olaylarını özel S3 bucket'ınıza .csv dosyaları olarak kaydedebileceksiniz. Bu entegrasyonu kurmak için S3 uyumlu depolama konsolunuzda ve Adapty Attribution kontrol panelinde birkaç basit adımı izlemeniz gerekecek. :::note Adapty Attribution verilerinizi her **24 saatte bir** saat 04:00 UTC'de gönderir. Her dosya, UTC saatine göre önceki takvim günü boyunca oluşturulan tüm etkinliklerin verilerini içerir. Örneğin, 8 Mart'ta UTC 04:00'te otomatik olarak dışa aktarılan veriler, 7 Mart'ta UTC 00:00:00 ile 23:59:59 arasında oluşturulan tüm etkinlikleri kapsar. ::: ## Özel S3 entegrasyonunu kurma \{#set-up-custom-s3-integration\} Veri almaya başlamak için Adapty Attribution'da entegrasyonu yapılandırın: 1. [**Integrations** -> **Custom S3**](https://app.adapty.io/ua/integrations/custom-s3) bölümüne gidin. 2. **Export install events to custom S3** geçiş düğmesini açın. 3. Özel S3 depolama alanınızla Adapty Attribution profilleri arasındaki bağlantıyı kurmak için gerekli alanları doldurun. | Alan | Açıklama | |:----------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Access Key ID** | S3 uyumlu depolama hizmetinize bir kullanıcı veya uygulamanın erişimini doğrulamak için kullanılan benzersiz tanımlayıcı. Bu kimliği depolama sağlayıcınızın konsolunda bulabilirsiniz. | | **Secret Access Key** | S3 uyumlu depolama hizmetinize erişimi doğrulamak için Access Key ID ile birlikte kullanılan özel anahtar. Bu anahtarı depolama sağlayıcınızın konsolunda bulabilirsiniz. | | **S3 Bucket Name** | Depolama ortamınızdaki belirli bir S3 bucket'ını tanımlayan, küresel olarak benzersiz ad. S3 bucket'ları, kullanıcıların dosyalar ve görseller gibi veri nesnelerini bulutta depolamasına ve almasına olanak tanıyan basit bir depolama hizmetidir. | | **Region** (İsteğe bağlı) | Bölgenizi Yönetim Konsolu'ndan alabilirsiniz. | | **Folder Inside the Bucket** (İsteğe bağlı) | Seçili S3 bucket'ının içinde oluşturmak istediğiniz klasörün adı. S3'ün klasörleri, nesne anahtar önekleri kullanarak simüle ettiğini unutmayın; bu önekler aslında klasör adlarıdır. | | **Custom Endpoint URL** | S3 uyumlu depolama hizmetinizin endpoint URL'si. Bu, depolama sağlayıcınız tarafından sağlanmalıdır (ör. MinIO, DigitalOcean Spaces, Wasabi vb.). | :::note S3 bucket adı alanında iç içe dizinler de belirtebilirsiniz, ör. `adapty-ua-events/com.sample-app` ::: ## Manuel veri dışa aktarımı \{#manual-data-export\} Otomatik etkinlik verisi dışa aktarımına ek olarak, Adapty Attribution; özel S3 depolama alanınıza manuel dosya dışa aktarımı da sunar. Bu özellik sayesinde kullanıcı edinim verilerini dilediğiniz tarihe göre seçerek S3 bucket'ınıza manuel olarak aktarabilirsiniz. Böylece hangi verileri ne zaman dışa aktaracağınız konusunda tam kontrol sizde olur. ## Tablo yapısı \{#table-structure\} Özel S3 entegrasyonunda Adapty Attribution, kurulum olaylarına ait geçmişe dönük verileri depolamak için bir tablo sağlar. Bu tablo; kullanıcı profili, gelir ve kazanç bilgileri ile kaynak mağaza gibi çeşitli veri noktalarını içerir. :::warning Bu yapının zamanla büyüyebileceğini unutmayın; bizim tarafımızdan veya birlikte çalıştığımız üçüncü taraflar tarafından yeni veriler eklenebilir. Bu yapıyı işleyen kodunuzun yeterince dayanıklı olduğundan ve yapının tamamına değil, belirli alanlara dayandığından emin olun. ::: Olaylara ait tablo yapısı aşağıdaki gibidir: | Sütun | Açıklama | |--------------------------|-------------------------------------------| | `adapty_profile_id` | Benzersiz Adapty profil tanımlayıcısı | | `install_id` | Benzersiz kurulum tanımlayıcısı | | `created_at` | Kayıt oluşturma zaman damgası (ISO 8601) | | `installed_at` | Uygulama kurulum zaman damgası (ISO 8601) | | `store` | Uygulama mağazası (`ios`, `android`) | | `country` | Kullanıcının ülke kodu (ISO 3166-1 alpha-2) | | `ip_address` | İstemci IP adresi | | `idfa` | iOS Reklamverenler için Tanımlayıcı | | `idfv` | iOS Satıcılar için Tanımlayıcı | | `gaid` | Google Reklam Kimliği (Android) | | `android_id` | Android cihaz kimliği | | `app_set_id` | Android Uygulama Set Kimliği | | `bundle_id` | Uygulama bundle tanımlayıcısı (ör. `com.example.app`) | | `device_brand` | Cihaz markası (ör. `Apple`, `Samsung`) | | `device_model` | Cihaz modeli (ör. `iPhone15,2`) | | `os_version` | Ana işletim sistemi sürümü | | `app_version` | Adapty SDK tarafından bildirilen uygulama sürümü | | `sdk_version` | Adapty SDK sürümü | | `channel` | Attribution kanalı | | `campaign_id` | Kampanya tanımlayıcısı | | `campaign_name` | Kampanya adı | | `adset_id` | Reklam seti tanımlayıcısı | | `adset_name` | Reklam seti adı | | `ad_id` | Reklam tanımlayıcısı | | `ad_name` | Reklam adı | | `keyword_id` | Anahtar kelime tanımlayıcısı | | `keyword_name` | Anahtar kelime adı | | `asa_org_id` | Apple Search Ads organizasyon kimliği | | `asa_keyword_match_type` | ASA anahtar kelime eşleşme türü (`Exact`, `Broad`) | | `asa_attribution` | ASA attribution verisi (JSON dizesi) | | `asa_conversion_type` | ASA dönüşüm türü | | `asa_country_or_region` | ASA ülkesi veya bölgesi | | `asa_creative_set_name` | ASA kreatif set adı | | `fbclid` | Facebook Tıklama Kimliği | | `ttclid` | TikTok Tıklama Kimliği | | `utm_source` | UTM kaynak parametresi | | `utm_medium` | UTM medium parametresi | | `utm_campaign` | UTM kampanya parametresi | | `utm_term` | UTM terim parametresi | | `utm_content` | UTM içerik parametresi | --- # File: ua-amazon-s3 --- --- title: "Adapty Attribution'da Amazon S3" description: "Gelişmiş analitik ve raporlama için kullanıcı edinme verilerini S3'e aktarın." --- Adapty Attribution'ın Amazon S3 entegrasyonu, kullanıcı edinim kampanya verilerini güvenli bir şekilde tek bir merkezi konumda saklamanızı sağlar. Kampanya performans verilerinizi, attribution verilerinizi ve kullanıcı edinim etkinliklerinizi Amazon S3 bucket'ınıza .csv dosyaları olarak kaydedebilirsiniz. Bu entegrasyonu kurmak için AWS Console ve Adapty Attribution kontrol panelinde birkaç basit adımı izlemeniz gerekecek. :::note Adapty Attribution verilerinizi her **24 saatte bir**, 04:00 UTC'de gönderir. Her dosya, önceki takvim gününe (UTC) ait tüm etkinlik verilerini içerir. Örneğin, 8 Mart'ta 04:00 UTC'de otomatik olarak dışa aktarılan dosya, 7 Mart'ta 00:00:00 ile 23:59:59 UTC arasında oluşturulan tüm etkinlikleri kapsar. ::: ## Amazon S3 entegrasyonu nasıl kurulur \{#how-to-set-up-amazon-s3-integration\} Veri almaya başlamak için aşağıdaki bilgilere ihtiyacınız olacak: 1. Access key ID 2. Secret access key 3. S3 bucket adı 4. S3 bucket içindeki klasör adı :::note İç içe dizinler Amazon S3 bucket adı alanında iç içe dizinler belirtebilirsiniz; örneğin: adapty-ua-events/com.sample-app ::: ### Adım 1. Amazon S3 kimlik bilgilerini oluşturun \{#step-1-create-amazon-s3-credentials\} Bu kılavuz, AWS Console'da gerekli kimlik bilgilerini oluşturmanıza yardımcı olacak. #### 1.1. Erişim Politikası Oluşturma \{#11-create-access-policy\} 1. AWS Console'unuzda [IAM Policy Dashboard](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/policies) sayfasına gidin 2. **Create Policy** seçeneğini seçin <img src="/assets/shared/img/7af075c-CleanShot_2023-03-21_at_10.52.002x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Politika düzenleyicisine aşağıdaki JSON'ı yapıştırın ve `adapty-s3-integration-test` kısmını kendi bucket adınızla değiştirin: ```json showLineNumbers title="Json" { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowListObjectsInBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::adapty-s3-integration-test" }, { "Sid": "AllowAllObjectActions", "Effect": "Allow", "Action": "s3:*Object", "Resource": [ "arn:aws:s3:::adapty-s3-integration-test/*", "arn:aws:s3:::adapty-s3-integration-test" ] }, { "Sid": "AllowBucketLocation", "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::adapty-s3-integration-test" } ] } ``` <img src="/assets/shared/img/d4e474a-CleanShot_2023-03-21_at_10.56.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Politika yapılandırmasını tamamladıktan sonra isteğe bağlı olarak etiket ekleyebilir, ardından son adıma geçmek için **Next** düğmesine tıklayabilirsiniz 5. Bu adımda politikanıza bir ad verin ve oluşturma işlemini tamamlamak için **Create policy** düğmesine tıklayın <img src="/assets/shared/img/7dcb02f-CleanShot_2023-03-21_at_11.03.372x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 1.2. IAM kullanıcısı oluşturma \{#12-create-iam-user\} Adapty Attribution'ın ham veri raporlarını bucket'ınıza yükleyebilmesi için, ilgili bucket'a yazma erişimi olan bir kullanıcının Access Key ID ve Secret Access Key bilgilerini sağlamanız gerekecektir. 1. IAM Console'a gidin ve [Users bölümünü](https://console.aws.amazon.com/iamv2/home#/users) seçin 2. **Add users** düğmesine tıklayın <img src="/assets/shared/img/bb612c8-CleanShot_2023-03-21_at_11.12.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Kullanıcıya bir ad verin, **Access key – Programmatic access** seçeneğini işaretleyin ve izinler adımına geçin <img src="/assets/shared/img/467ee4d-j6aoX.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Bir sonraki adımda **Add user to group** seçeneğini belirleyin ve ardından **Create group** düğmesine tıklayın <img src="/assets/shared/img/bfd0e80-CleanShot_2023-03-21_at_11.24.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Kullanıcı Grubuna bir ad verin ve daha önce oluşturduğunuz politikayı seçin 6. Politikayı seçtikten sonra işlemi tamamlamak için **Create group** düğmesine tıklayın <img src="/assets/shared/img/df29c12-CleanShot_2023-03-21_at_11.28.052x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Grubu başarıyla oluşturduktan sonra **seçin** ve bir sonraki adıma geçin <img src="/assets/shared/img/1f3722e-CleanShot_2023-03-21_at_11.36.192x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. Bu bölümün son adımı olduğundan, **Create User** düğmesine tıklayarak devam edebilirsiniz <img src="/assets/shared/img/ea43722-CleanShot_2023-03-21_at_11.40.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. Son olarak kimlik bilgilerini **.csv formatında indirebilir** ya da doğrudan kontrol panelinden kopyalayıp yapıştırabilirsiniz <img src="/assets/shared/img/bcf35e1-S3created.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Adım 2. Adapty Attribution'da entegrasyonu yapılandırın \{#step-2-configure-integration-in-adapty-attribution\} 1. [**Integrations** -> **Amazon S3**](https://app.adapty.io/ua/integrations/s3) bölümüne gidin. 2. **Export install events to Amazon S3** geçişini etkinleştirin. 3. Amazon S3 ile Adapty Attribution profillerini bağlamak için aşağıdaki alanları doldurun: | Alan | Açıklama | |:-----------------------------| :----------------------------------------------------------- | | **Access Key ID** | AWS hizmetine erişimi doğrulamak için kullanılan benzersiz bir tanımlayıcı. Bu kimliği indirilen [csv dosyasında](ua-amazon-s3#step-1-create-amazon-s3-credentials) bulabilirsiniz. | | **Secret Access Key** | AWS hizmetine erişimi doğrulamak için Access Key ID ile birlikte kullanılan özel bir anahtar. Bu anahtarı indirilen [csv dosyasında](ua-amazon-s3#step-1-create-amazon-s3-credentials) bulabilirsiniz. | | **S3 Bucket Name** | AWS bulutundaki belirli bir S3 bucket'ını tanımlayan, küresel ölçekte benzersiz bir ad. S3 bucket'ları, kullanıcıların dosya ve resim gibi veri nesnelerini bulutta depolamasına ve almasına olanak tanıyan basit bir depolama hizmetidir. | | **Folder Inside the Bucket** | Seçilen S3 bucket'ının içinde oluşturmak istediğiniz klasörün adı. S3'ün klasörleri, nesne anahtar önekleri (yani klasör adları) kullanarak simüle ettiğini unutmayın. | | **Region** (İsteğe bağlı) | Region bilginizi AWS Management Console'da IAM kullanıcı hesabınızdan alabilirsiniz. | ## Manuel veri dışa aktarımı \{#manual-data-export\} Adapty Attribution, Amazon S3'e otomatik olay verisi dışa aktarımına ek olarak manuel dosya dışa aktarma özelliği de sunar. Bu özellik sayesinde kullanıcı edinme verileri için belirli bir tarih seçerek bu verileri S3 bucket'ınıza manuel olarak aktarabilirsiniz. Böylece hangi verileri ne zaman dışa aktaracağınız üzerinde daha fazla kontrol sahibi olursunuz. ## Tablo yapısı \{#table-structure\} AWS S3 entegrasyonunda Adapty Attribution, kurulum etkinliklerine ait geçmiş verileri depolamak için bir tablo sunar. Bu tablo; kullanıcı profili, gelir ve kazançlar ile kaynak mağaza gibi çeşitli veri noktalarına ilişkin bilgiler içerir. :::warning Bu yapının zamanla büyüyebileceğini unutmayın; biz veya birlikte çalıştığımız üçüncü taraflar yeni veriler ekleyebilir. Bu yapıyı işleyen kodunuzun yeterince sağlam olduğundan ve yapının tamamına değil, belirli alanlara dayandığından emin olun. ::: Etkinliklere ait tablo yapısı aşağıdaki gibidir: | Sütun | Açıklama | |--------------------------|-------------------------------------------| | `adapty_profile_id` | Benzersiz Adapty profil tanımlayıcısı | | `install_id` | Benzersiz kurulum tanımlayıcısı | | `created_at` | Kayıt oluşturma zaman damgası (ISO 8601) | | `installed_at` | Uygulama kurulum zaman damgası (ISO 8601) | | `store` | Uygulama mağazası (`ios`, `android`) | | `country` | Kullanıcının ülke kodu (ISO 3166-1 alpha-2) | | `ip_address` | İstemci IP adresi | | `idfa` | iOS Reklamverenler için Tanımlayıcı | | `idfv` | iOS Satıcılar için Tanımlayıcı | | `gaid` | Google Reklam Kimliği (Android) | | `android_id` | Android cihaz kimliği | | `app_set_id` | Android App Set kimliği | | `channel` | Attribution kanalı | | `campaign_id` | Kampanya tanımlayıcısı | | `campaign_name` | Kampanya adı | | `adset_id` | Reklam seti tanımlayıcısı | | `adset_name` | Reklam seti adı | | `ad_id` | Reklam tanımlayıcısı | | `ad_name` | Reklam adı | | `keyword_id` | Anahtar kelime tanımlayıcısı | | `keyword_name` | Anahtar kelime adı | | `asa_org_id` | Apple Search Ads organizasyon kimliği | | `asa_keyword_match_type` | ASA anahtar kelime eşleşme türü (`Exact`, `Broad`) | | `asa_attribution` | ASA attribution verisi (JSON dizesi) | | `asa_conversion_type` | ASA dönüşüm türü | | `asa_country_or_region` | ASA ülke veya bölge | | `asa_creative_set_name` | ASA yaratıcı set adı | | `fbclid` | Facebook Tıklama Kimliği | | `ttclid` | TikTok Tıklama Kimliği | | `utm_source` | UTM kaynak parametresi | | `utm_medium` | UTM medium parametresi | | `utm_campaign` | UTM kampanya parametresi | | `utm_term` | UTM terim parametresi | | `utm_content` | UTM içerik parametresi | --- # File: ua-google-cloud-storage --- --- title: "Adapty Attribution'da Google Cloud Storage" description: "Güvenli kullanıcı edinme verisi depolama için Google Cloud Storage'ı Adapty Attribution ile entegre edin." --- Adapty Attribution'ın Google Cloud Storage ile entegrasyonu, kullanıcı edinme kampanya verilerinizi tek bir merkezi konumda güvenli bir şekilde saklamanızı sağlar. Kampanya performans verilerinizi, attribution verilerinizi ve kullanıcı edinme etkinliklerinizi Google Cloud Storage bucket'ınıza .csv dosyaları olarak kaydedebilirsiniz. Bu entegrasyonu kurmak için Google Cloud Console ve Adapty Attribution Kontrol Paneli'nde birkaç basit adımı izlemeniz gerekecek. :::note Zamanlama Adapty Attribution, verilerinizi her gün UTC 04:00'te Google Cloud Storage'a gönderir. Her dosya, UTC'de önceki takvim gününün tamamına ait olay verilerini içerir. Örneğin, 8 Mart'ta 04:00 UTC'de otomatik olarak dışa aktarılan veriler, 7 Mart'ta 00:00:00 ile 23:59:59 UTC arasında oluşturulan tüm olayları kapsar. ::: ## Google Cloud Storage entegrasyonu nasıl kurulur \{#how-to-set-up-google-cloud-storage-integration\} ### Adım 1. Google Cloud Storage kimlik bilgilerini oluşturma \{#step-1-create-google-cloud-storage-credentials\} Bu kılavuz, Google Cloud Platform Console'da gerekli kimlik bilgilerini oluşturmanıza yardımcı olacaktır. Adapty Attribution'ın ham veri raporlarını belirlediğiniz bucket'a yükleyebilmesi için servis hesabının anahtarı ve ilgili bucket'a yazma erişimi gereklidir. Servis hesabı anahtarını sağlayarak ve bucket'a yazma erişimi vererek, Adapty Attribution'ın ham veri raporlarını kendi platformundan depolama ortamınıza güvenli ve verimli bir şekilde aktarmasına izin vermiş olursunuz. :::warning Lütfen dikkat edin: yalnızca Service Account HMAC key yetkilendirmesini destekliyoruz. Bu nedenle, Google Cloud Storage'a düzgün erişim sağlamak için Service Account HMAC key'inizin "Storage Object Viewer", "Storage Legacy Bucket Writer" ve "Storage Object Creator" rollerine sahip olduğundan emin olmanız gerekmektedir. ::: #### 2.1. Service Account Oluşturma \{#21-create-service-account\} 1. Google Cloud hesabınızın [IAM](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) bölümüne gidin ve ilgili projeyi seçin ya da yeni bir proje oluşturun <img src="/assets/shared/img/30a81ef-CleanShot_2023-03-17_at_15.22.142x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ardından, "+ CREATE SERVICE ACCOUNT" düğmesine tıklayarak Adapty Attribution için yeni bir hizmet hesabı oluşturun <img src="/assets/shared/img/98f8ebf-CleanShot_2023-03-17_at_15.40.062x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Erişim daha sonraki bir aşamada verileceğinden, ilk adımdaki alanları doldurun. Bu sayfa hakkında daha fazla ayrıntı okumak için belgelere [buradan](https://docs.cloud.google.com/iam/docs/service-accounts-create) ulaşabilirsiniz. <img src="/assets/shared/img/2190c50-CleanShot_2023-03-17_at_15.48.552x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. [Özel bir JSON anahtarı](https://docs.cloud.google.com/iam/docs/keys-create-delete) oluşturmak ve indirmek için KEYS bölümüne gidin ve "ADD KEY" düğmesine tıklayın <img src="/assets/shared/img/8a45468-CleanShot_2023-03-17_at_15.58.092x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. DETAILS bölümünde, yeni oluşturulan servis hesabına bağlı Email değerini bulun ve kopyalayın. Bu bilgi, ilerleyen adımlarda hesabı yetkilendirmek ve bucket'a yazma izni vermek için gerekli olacaktır. <img src="/assets/shared/img/6ccd0f0-CleanShot_2023-03-17_at_16.03.162x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 2.2. Bucket İzinlerini Yapılandırın \{#22-configure-bucket-permissions\} 6. Google Cloud Storage'ın [Buckets](https://console.cloud.google.com/storage/browser) sayfasına gidin ve mevcut bir bucket seçin ya da Adapty Attribution'dan gelen kullanıcı edinme verisi raporlarını depolamak için yeni bir tane oluşturun. 7. **PERMISSIONS** bölümüne gidin ve [GRANT ACCESS](https://docs.cloud.google.com/identity/docs/how-to?hl=en) seçeneğini belirleyin. <img src="/assets/shared/img/3cdd937-CleanShot_2023-03-17_at_16.14.232x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. PERMISSIONS bölümünde, daha önce beşinci adımda elde edilen hizmet hesabının E-posta adresini girin, ardından Storage Object Creator rolünü seçin 9. Son olarak, değişiklikleri uygulamak için SAVE'e tıklayın <img src="/assets/shared/img/62801f4-CleanShot_2023-03-17_at_16.17.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 10. Bucket adını ileride kullanmak üzere not almayı unutmayın 11. Bu adımları tamamladıktan sonra Google Cloud Console'daki gerekli kurulum adımlarını başarıyla bitirmiş olacaksınız! Son adım, bucket adını girmek ve Adapty Attribution'da kullanmak üzere JSON dosyasını indirmektir <img src="/assets/shared/img/c967e16-CleanShot_2023-03-17_at_16.23.332x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Adım 2. Adapty Attribution'da entegrasyonu yapılandırın \{#step-2-configure-integration-in-adapty-attribution\} 1. [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/ua/integrations/google-cloud-storage) sayfasına gidin 2. **Export install events to Google Cloud Storage** seçeneğini açın 3. Google Cloud Storage ile Adapty Attribution arasında bağlantı kurmak için gerekli alanları doldurun: | Alan | Açıklama | |:------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Google Cloud service account key file** | İndirilen özel [JSON anahtar dosyası](ua-google-cloud-storage#step-1-create-google-cloud-storage-credentials). | | **Google Cloud bucket name** | Verilerinizi depolamak istediğiniz Google Cloud Storage'daki bucket adı. Google Cloud Storage ortamında benzersiz olmalı ve boşluk içermemelidir. | | **Folder inside the bucket** | Verilerinizi depolamak istediğiniz bucket içindeki klasörün adı. Bucket içinde benzersiz olmalı ve verilerinizi düzenlemek için kullanılabilir. Bu alan isteğe bağlıdır. | ## Manuel veri dışa aktarma \{#manual-data-export\} Google Cloud Storage'a otomatik etkinlik verisi dışa aktarmanın yanı sıra Adapty UA, manuel dosya dışa aktarma özelliği de sunar. Bu özellik sayesinde belirli bir tarih için kullanıcı edinimi verilerini seçip GCS bucket'ınıza manuel olarak aktarabilirsiniz. Bu, hangi verileri ne zaman dışa aktaracağınız konusunda daha fazla kontrol sahibi olmanızı sağlar. ## Tablo yapısı \{#table-structure\} Google Cloud Storage entegrasyonunda Adapty Attribution, kurulum etkinliklerine ait geçmiş verileri depolamak için bir tablo sağlar. Tablo; kullanıcı profili, gelir ve kazançlar ile kaynak mağaza gibi birçok veri noktasına ilişkin bilgiler içerir. :::warning Bu yapının zamanla büyüyebileceğini unutmayın; bizim tarafımızdan veya birlikte çalıştığımız üçüncü taraflarca yeni veriler eklenebilir. Bu yapıyı işleyen kodunuzun yeterince sağlam olduğundan ve belirli alanlara dayandığından, ancak yapının tamamına bağımlı olmadığından emin olun. ::: Etkinlikler için tablo yapısı aşağıdaki gibidir: | Sütun | Açıklama | |--------------------------|-------------------------------------------------------| | `adapty_profile_id` | Benzersiz Adapty profil tanımlayıcısı | | `install_id` | Benzersiz kurulum tanımlayıcısı | | `created_at` | Kayıt oluşturma zaman damgası (ISO 8601) | | `installed_at` | Uygulama kurulum zaman damgası (ISO 8601) | | `store` | Uygulama mağazası (`ios`, `android`) | | `country` | Kullanıcının ülke kodu (ISO 3166-1 alpha-2) | | `ip_address` | İstemci IP adresi | | `idfa` | iOS Reklamverenler için Tanımlayıcı | | `idfv` | iOS Satıcılar için Tanımlayıcı | | `gaid` | Google Reklamcılık Kimliği (Android) | | `android_id` | Android cihaz kimliği | | `app_set_id` | Android App Set Kimliği | | `channel` | Attribution kanalı | | `campaign_id` | Kampanya tanımlayıcısı | | `campaign_name` | Kampanya adı | | `adset_id` | Reklam seti tanımlayıcısı | | `adset_name` | Reklam seti adı | | `ad_id` | Reklam tanımlayıcısı | | `ad_name` | Reklam adı | | `keyword_id` | Anahtar kelime tanımlayıcısı | | `keyword_name` | Anahtar kelime adı | | `asa_org_id` | Apple Search Ads organizasyon kimliği | | `asa_keyword_match_type` | ASA anahtar kelime eşleşme türü (`Exact`, `Broad`) | | `asa_attribution` | ASA attribution verisi (JSON dizesi) | | `asa_conversion_type` | ASA dönüşüm türü | | `asa_country_or_region` | ASA ülkesi veya bölgesi | | `asa_creative_set_name` | ASA kreatif set adı | | `fbclid` | Facebook Tıklama Kimliği | | `ttclid` | TikTok Tıklama Kimliği | | `utm_source` | UTM kaynak parametresi | | `utm_medium` | UTM medium parametresi | | `utm_campaign` | UTM kampanya parametresi | | `utm_term` | UTM term parametresi | | `utm_content` | UTM içerik parametresi | --- # File: adapty-mail --- --- title: "Adapty Mail" description: "Deneme kullanıcılarını ücretli abonelere dönüştüren yapay zeka destekli e-posta kampanyaları." --- <CustomDocCardList ids={['mail-get-started', 'mail-brand', 'mail-collect-emails', 'mail-send-data-via-api', 'mail-sending-domain', 'mail-create-campaign', 'mail-analytics']} /> Adapty Mail, Adapty kullanıcı verilerinizi kullanarak deneme kullanıcılarını ücretli abonelere dönüştüren yapay zeka destekli e-posta dizileri oluşturur. Kampanyaları oluşturmak, göndermek ve attribution yapmak için Adapty projenizde zaten bulunan profil verilerini kullanır — ayrı bir e-posta platformuna gerek yoktur. ## Neden Adapty Mail? \{#why-adapty-mail\} Hedefli e-posta kampanyaları göndermek; metin yazarlığı, tasarım, gönderim altyapısı ve gelir attribution'ı gibi konuları gerektirir. Bunların her biri ayrı bir sorun demektir. Adapty Mail hepsini çözer. Marka profiliniz, mağaza URL'niz ve eklediğiniz diğer kaynaklar üzerinden oluşturulur; 2 dakikadan kısa sürede tam bir e-posta dizisi üretilir — kişiselleştirilmiş ödeme bağlantıları ve satın alma attribution'ı ile kendi alan adınızdan gönderilir. ## Nasıl çalışır \{#how-it-works\} 1. **E-postaları toplayın**: Uygulamanız, SDK aracılığıyla kullanıcı e-postalarını ve `customer_user_id` değerlerini Adapty'e iletir. Adapty Mail bu verileri alıcıları tanımlamak ve her satın almayı yönlendiren belirli e-postaya geliri attribute etmek için kullanır. Bu verileri [Adapty Mail API](mail-send-data-via-api) ile sunucunuzdan da gönderebilirsiniz. 2. **Web paywall oluşturun**: Her e-postanın bağlandığı ödeme sayfası. 3. **Dizi oluşturun**: Yapay zeka, marka profilinizi kullanarak 1–15 e-posta üretir — metin, tasarım, kapak görselleri ve uygulamanızın kategorisi ile marka sesine göre kişiselleştirilmiş ödeme bağlantıları. 4. **Flow başlatın**: Bir tetikleyici (hiç satın almamış, yenileme iptal edilmiş, ödeme sorunu, abonelik süresi dolmuş veya para iadesi yapılmış) ve bir segment seçin, ardından kampanyanızı ekleyin. E-postalar otomatik olarak gönderilmeye başlar ve e-posta kaynaklı satın almalardan elde edilen gelir, dönüşümü sağlayan belirli e-postaya attribute edilir. ## Gereksinimler \{#requirements\} Adapty Mail'i kullanmak için şunlara ihtiyacınız vardır: - Bir Adapty hesabı - Uygulamanızda e-posta toplama kurulumu — bkz. [Kullanıcı e-postalarını toplama](mail-collect-emails) - Adapty SDK'nızda yapılandırılmış `customer_user_id` - DNS ayarlarına erişiminizin bulunduğu, kontrolünüzdeki bir alan adı - Bir web ödeme sağlayıcısı (Stripe, Paddle veya PayPal) ## Başlarken \{#get-started\} Kurulumu tamamlamak ve ilk kampanyanızı başlatmak için [Adapty Mail'e başlarken](mail-get-started) kılavuzunu takip edin. --- # File: mail-get-started --- --- title: "Adapty Mail'e Başlarken" description: "Adapty Mail'i kurun ve ilk e-posta flow'unuzu başlatın." --- Bu kılavuzda Adapty Mail'i kuracak ve ilk e-posta flow'unuzu başlatacaksınız. :::note Adapty SDK kullanmadan, kendi sunucunuzdan da Adapty Mail'e veri gönderebilirsiniz. Kullanıcı e-postalarını ve satın alımlarını backend'inizde zaten tutuyorsanız veya başka bir kaynaktan abone içe aktarıyorsanız, bkz. [Adapty Mail API aracılığıyla e-posta ve işlem gönderme](mail-send-data-via-api). ::: Kurulum altı bölümden oluşmaktadır: 1. [Adapty SDK'nızı yapılandırın](#1-configure-your-adapty-sdk) 2. [Gönderme domain'inizi ayarlayın](#2-set-up-your-sending-domain) 3. [Bir web paywall'u oluşturun](#3-create-a-web-paywall) 4. [Yapay zeka ile bir kampanya oluşturun](#4-generate-a-campaign-with-ai) 5. [Bir akış başlatın](#5-launch-a-flow) 6. [Gönderimi etkinleştirin](#6-enable-sending) :::tip Adapty üzerinden Adapty Mail'e kaydolduysanız, **brand profili** otomatik olarak projenizin mağaza URL'sinden oluşturulur. İstediğiniz zaman **Brand** sayfasını açıp inceleyebilir veya düzenleyebilirsiniz — bkz. [Brand](mail-brand). Bağımsız kaydolduysanız, kampanya veya web paywall oluşturmadan önce aynı sayfada markanızı ayarlayın. ::: ## Başlamadan önce \{#before-you-start\} Başlamadan önce aşağıdakilerin hazır olduğundan emin olun: - **DNS erişimi**: Kök alan adınıza kayıt ekleyebiliyorsunuz. - **Web ödeme sağlayıcısı**: Abonelik ürünlerinizin yapılandırılmış olduğu bir Stripe, Paddle veya PayPal hesabınız var. ## 1. Adapty SDK'nızı Yapılandırın \{#1-configure-your-adapty-sdk\} :::important Adapty Mail **bağımsız bir üründür**. Paywall'larınız, abonelikleriniz veya analizleriniz Adapty tarafından yönetilmese bile kullanabilirsiniz — tüm altyapınızı taşımanız gerekmez. Doğru gelir verisi elde etmek için minimum kurulum, Adapty SDK'yı gözlemci modunda yüklemek ve App Store sunucu bildirimlerini etkinleştirmektir. ::: Adapty Mail'in uygulamanızdan ihtiyaç duyduğu üç şey vardır: satın alma verisi (her dönüşümü sağlayan e-postaya geliri atfedebilmek için), kararlı bir kullanıcı tanımlayıcısı ve kullanıcı e-posta adresleri. 1. **Adapty'nin gelirinizi takip etmesine izin verin.** İlk adım, uygulama içi satın almalarınızın zaten mevcut olup olmadığına bağlıdır: - **Adapty ile uygulama içi satın almalarınızı zaten uyguladıysanız**, bu aşamada başka bir şey yapmanıza gerek yok. - **Adapty olmadan uygulama içi satın almalarınızı zaten uyguladıysanız** ve Adapty'ye geçmeyi planlamıyorsanız, platformunuz için Adapty SDK'sını observer mode ile yükleyin. Bu aşamada yalnızca SDK'yı projenize eklemeniz, observer mode etkin şekilde başlatmanız ve işlemleri raporlamanız yeterlidir. Platform kılavuzları: [iOS](implement-observer-mode), [Android](implement-observer-mode-android), [React Native](implement-observer-mode-react-native), [Flutter](implement-observer-mode-flutter), [Unity](implement-observer-mode-unity), [Kotlin Multiplatform](implement-observer-mode-kmp), [Capacitor](implement-observer-mode-capacitor). - **Uygulama içi satın almalarınızı henüz uygulamadıysanız ve Adapty kullanmak istiyorsanız**, satın alma işlemlerini Adapty'ye devretmek için [hızlı başlangıç kılavuzundaki](quickstart) adımları tamamlayın. Ardından gelir ile ilgili güncellemeleri doğrudan App Store'dan almak için [Adapty'de App Store sunucu bildirimlerini etkinleştirin](enable-app-store-server-notifications). 2. **Kullanıcı kimliğini ayarlayın.** Backend kullanıcı kimliğinizi, Firebase UID'nizi veya benzer bir ID'yi; `Adapty.identify()` çağırarak ya da SDK başlatılırken `.activate()` metoduna `customerUserId` geçirerek iletin. `customer_user_id`, Adapty Mail'in kampanyaları, tıklamaları ve satın almaları doğru profile eşleştirmek için kullandığı tanımlayıcıdır. Platform kılavuzları: [iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Unity](unity-identifying-users), [Kotlin Multiplatform](kmp-identifying-users), [Capacitor](capacitor-identifying-users). 3. **Kullanıcı e-postalarını toplayın.** Kullanıcı uygulamanızda e-posta adresini girdiğinde (örneğin kayıt veya ödeme sırasında), e-posta özelliğiyle birlikte `updateProfile` çağrısı yaparak bunu Adapty'ye iletin. Bir kampanyanın her alıcısının bu değere sahip olması gerekir. Platform kılavuzları: [iOS](setting-user-attributes), [Android](android-setting-user-attributes), [React Native](react-native-setting-user-attributes), [Flutter](flutter-setting-user-attributes), [Unity](unity-setting-user-attributes), [Kotlin Multiplatform](kmp-setting-user-attributes), [Capacitor](capacitor-setting-user-attributes). Uygulamanız henüz e-posta toplamıyorsa [E-posta toplama stratejileri](mail-collect-emails#email-collection-strategies) sayfasına bakın. ## 2. Gönderim etki alanınızı ayarlayın \{#set-up-your-sending-domain\} Adapty Mail'i açın: Üst bilgideki Adapty logosuna tıklayın ve **Mail**'i seçin. Adapty Mail, kendi etki alanınızdan gönderim yapar. DNS kayıtlarını bir kez eklersiniz — tüm kampanyalar aynı doğrulanmış etki alanını kullanır. 1. Adapty Mail'de **Settings → Email Domains** bölümüne gidin. 2. Kök etki alanınızı girin (örneğin `yourapp.com`) ve **Preview**'a tıklayın. Yalnızca apex etki alanları kabul edilir — `app.yourapp.com` gibi alt etki alanları girişte reddedilir. 3. Adapty iki gönderim alt alanı (`mail.yourapp.com` ve `email.yourapp.com`) oluşturur. Gerekli DNS kayıtlarını görmek için **Confirm**'e tıklayın. 4. Alan adı kayıt kuruluşunuzda gösterilen 10 DNS kaydını ekleyin (alt alan başına 5 kayıt): - Alt alan başına 3 CNAME kaydı (DKIM) - Alt alan başına 1 MX kaydı (Mail-From) - Alt alan başına 1 TXT kaydı (SPF, `v=spf1 include:amazonses.com ~all`) 5. İsteğe bağlı olarak, kök alan adınıza bir DMARC TXT kaydı ekleyin (önerilir). 6. **Settings → Email Domains** sayfasına dönün ve **Check Verification**'a tıklayın. Doğrulama zamanlamasına genel bakış: - **Otomatik yoklama**: İlk kontrol, gönderimden yaklaşık 5 dakika sonra çalışır. Kayıtlar bulunana kadar aralıklar saatte bir'e kadar uzar. - **Manuel kontrol**: Anında kontrol tetiklemek için istediğiniz zaman **Check Verification** seçeneğine tıklayın. - **DNS yayılımı**: Genellikle birkaç dakika sürer; nadir durumlarda 48 saate kadar uzayabilir. - **Doğrulama penceresi**: 7 gün. Süre dolarsa DNS kayıtlarınız yerinde kalır — yeni bir pencere başlatmak için **Settings → Email Domains** bölümüne geri dönüp etki alanınızı tekrar girin. Kayıt türleri ve alan adı ısınma süreci hakkında ayrıntılı bilgi için bkz. [Gönderim alan adınızı ayarlayın](mail-sending-domain). ## 3. Gönderim alan adınızı ayarlayın \{#set-up-your-sending-domain\} Adapty Mail, kendi alan adınızdan gönderim yapar. DNS kayıtlarını bir kez eklersiniz — tüm kampanyalar aynı doğrulanmış alan adını kullanır. 1. Adapty Mail'de **Settings → Email Domains** bölümüne gidin. 2. Ana alan adınızı girin (örneğin, `yourapp.com`) ve **Preview**'e tıklayın. Yalnızca apex alan adları kabul edilir — `app.yourapp.com` gibi alt alan adları girişte reddedilir. 3. Adapty iki gönderim alt alan adı oluşturur (`mail.yourapp.com` ve `email.yourapp.com`). Gerekli DNS kayıtlarını görmek için **Confirm**'e tıklayın. 4. Domain kayıt sağlayıcınızda gösterilen 10 DNS kaydını ekleyin (her subdomain için 5): - Her subdomain için 3 CNAME kaydı (DKIM) - Her subdomain için 1 MX kaydı (Mail-From) - Her subdomain için 1 TXT kaydı (SPF, `v=spf1 include:amazonses.com ~all`) 5. İsteğe bağlı olarak, kök domaininize bir DMARC TXT kaydı ekleyin (önerilir). 6. **Settings → Email Domains** bölümüne geri dönün ve **Check Verification** butonuna tıklayın. Doğrulama süresine genel bakış: - **Otomatik yoklama**: İlk kontrol, gönderimin ardından yaklaşık 5 dakika sonra başlar. Kayıtlar bulunana kadar aralıklar saatte bire kadar uzar. - **Manuel kontrol**: Anında kontrol başlatmak için istediğiniz zaman **Check Verification** düğmesine tıklayın. - **DNS yayılımı**: Genellikle dakikalar içinde tamamlanır; nadir durumlarda 48 saate kadar sürebilir. - **Doğrulama penceresi**: 7 gün. Süre dolarsa DNS kayıtlarınız yerinde kalır — yeni bir pencere başlatmak için **Settings → Email Domains** bölümüne alan adınızı yeniden girin. Her kayıt türü ve alan adı ısınması hakkında ayrıntılı bilgi için bkz. [Gönderme alan adınızı kurma](mail-sending-domain). ### Seçenek A: Yapay Zeka ile Oluştur \{#option-a-generate-with-ai\} Sayfa, satır içi düğmeler içeren bir **Önkoşullar** listesi gösterir — önce sırayla bunları tamamlayın, ardından geri dönerek oluşturma işlemini başlatın. Liste; paywall builder'a giriş yapma, Stripe'ı bağlama, ürün ekleme ve sonucu inceleme adımlarını kapsar. Tam adımlar için bkz. [Ödemeyi yapılandırma](mail-checkout). Tüm önkoşullar yeşile döndüğünde, oluşturma iletişim kutusunu açmak için **Generate** düğmesine tıklayın: - **Environment**: **Production** veya **Sandbox** seçin. Sandbox, Stripe test modu ürünlerinizi kullanır ve geliştirme ile yerel ortamlar için güvenli varsayılandır. - **Plans**: En fazla **3 Stripe planı** seçin (her plan bir ürün + fiyattır). Bunlar, oluşturulan paywall'ın kullanıcılara ödeme sırasında sunduğu tekliflerdir. Derlemeyi başlatmak için **Generate**'e tıklayın. Tamamlandığında, incelemek ve yayımlamak için editörü açın. :::important Paywall, ödeme trafiğine hizmet verebilmesi için yayımlanmış olmalıdır. Yayımlanmamış paywall'lar, kullanıcılar e-posta ödeme bağlantılarına tıkladığında hata döndürür. ::: ### A Seçeneği: Yapay Zeka ile Oluştur \{#option-a-generate-with-ai\} 1. **Generate with AI** seçeneğini seçin. 2. **Log in to the paywall builder** butonuna tıklayın. Web paywall builder yeni bir sekmede açılır. Henüz oturum açmadıysanız Adapty kimlik bilgilerinizle giriş yapın. 3. Builder'da ödeme sağlayıcı entegrasyonunuzu (Stripe, Paddle veya PayPal) etkinleştirin. Ayrıntılar için [Web paywall yapılandırması](web-paywall-configuration) bölümüne bakın. 4. Adapty Mail'e dönün ve **Proceed to generation** butonuna tıklayın. 5. Oluşturulan paywallı inceleyin, ardından kaydedin ve yayınlayın. ## 4. Yapay zeka ile kampanya oluşturun \{#generate-a-campaign-with-ai\} Yapay zeka, markanıza özel olarak tüm e-posta dizisini sizin için oluşturur; metin, tasarım, hero görseller ve kişiselleştirilmiş ödeme bağlantıları dahil. 1. Adapty Mail'de **Campaigns** bölümüne gidin ve **Create** düğmesine tıklayın. 2. Kampanya adını belirleyin. 3. **Web paywall** açılır menüsünden önceki adımda eklediğiniz web paywallı seçin. 4. **E-posta oluştur**'a tıklayın. 5. Oluşturma iletişim kutusunu doldurun — ton, dil, isteğe bağlı özel bir komut istemi (en fazla 2.000 karakter) ve e-posta sayısı (1–15, varsayılan 4). Her alanın ne işe yaradığını öğrenmek için [Kampanya oluştur](mail-create-campaign) bölümüne bakın. 6. **Generate**'e (Oluştur) tıklayın. Oluşturma genellikle birkaç dakika sürer. Tamamlanamazsa sistem 5 dakika sonra zaman aşımına uğrar — bu durumda tekrar deneyin. 7. Her e-postayı önizleyin. Önizleme başlığında, önizlemenin nasıl görüneceğini kontrol eden bir **Theme toggle** (Tema değiştirici) (Auto, Light, Dark) bulunur — oluşturulan içerik tüm modlarda aynıdır. Tek tek e-postaları yeniden oluşturabilir, metinleri düzenleyebilir veya ayrıntılı kontrol için HTML düzenleyiciyi açabilirsiniz. 8. Kampanyayı kaydetmek için **Create**'e tıklayın. Kampanya **taslak** olarak kaydedilir ve henüz gönderilmez — kampanyalar yalnızca bir flow'a eklendikten sonra (bir sonraki adım) yayına girer. Kampanya düzenleyicisinde ayrı bir "yayınla" işlemi yoktur. ## 5. Bir akış başlatın \{#launch-a-flow\} Bir akış, bir **tetikleyici**'yi (aboneliğin sona ermesi gibi bir olay) bir **segment** ile eşleştirir ve o segmente seçtiğiniz **kampanyayı** gönderir. Adapty Mail, her birinin kendine özgü akış görünümü olan beş sabit tetikleyiciyle birlikte gelir. 1. Adapty Mail'de **Flows** bölümüne gidin, ardından yapılandırmak istediğiniz tetikleyiciyi açın: - **Never purchased** — kaydolmuş ancak henüz satın alma yapmamış kullanıcılar. - **Renewal cancelled** — otomatik yenilemeyi kapattığı halde aktif aboneliği devam eden kullanıcılar. - **Billing issue** — ödeme başarısız, kart reddedilmiş veya süresi dolmuş ya da ek sürede olan kullanıcılar. - **Expired** — aboneliği sona ermiş ve erişimi kalkmış kullanıcılar. - **Refunded** — satın alma sonrasında para iadesi talep etmiş kullanıcılar. Her tetikleyicinin amacı ve ton rehberliği için [Flows](mail-flows) sayfasına bakın. 2. Diyaloğu açmak için **Create** düğmesine tıklayın. 3. İletişim kutusunda: - Bir **Segment** seçin (örneğin, bu tetikleyiciye ulaşan herkesi hedeflemek için **All Users** ya da profil özelliklerine göre yeni bir segment oluşturun). - İçerik türünü **Campaign** olarak bırakın (A/B Testi seçeneği [A/B testi](mail-ab-testing) bölümünde ele alınmaktadır). - 4. Adımda kaydettiğiniz **Campaign**'i seçin. 4. **Save**'e tıklayın. Flow hemen yayına girer — ayrı bir başlatma adımı yoktur. Bu noktadan itibaren segmentle eşleşen kullanıcılar, tetikleyici olayına ulaştıkları anda kampanyayı almaya başlar. :::note Aynı tetikleyiciye birden fazla segment → kampanya satırı ekleyebilirsiniz; bunlar öncelik sırasına göre çalışır. **All Users** satırı, kullanılıyorsa, daha spesifik bir segmentle eşleşmeyen herkesi yakalamak için en sona (en düşük önceliğe) yerleştirilmelidir. ::: ## 6. Gönderimi etkinleştirin \{#enable-sending\} Şimdiye kadar kampanyanızı kurdunuz, ancak henüz çalışmıyor — abonelik etkinliklerini Adapty Mail ile senkronize eden **Adapty entegrasyonu** hâlâ kapalı. Bunu açmak son adımdır: etkinlikler akmaya, segmentler eşleşmeye ve e-postalar gönderilmeye başlar. Bu adım yalnızca 5. adım tamamlandıktan sonra açılır. Bir akış başlatmadan önce, **Settings → Integrations** bölümündeki **Enable** düğmesi *"Set up at least one flow before enabling Adapty integration."* ipucu mesajıyla devre dışı kalır. 1. Adapty Mail'de **Settings → Integrations** bölümüne gidin. 2. **Enable Adapty integration** (ya da daha önce kurulum yapıldıysa **Enable**) seçeneğine tıklayın. Etkinleştirildiğinde, Adapty tüm abonelik olaylarını — yeni abonelikler, yenilemeler, denemeler, dönüşümler, iadeler, ödeme sorunları — Adapty Mail'e gönderir. Bu olaylar segment üyeliğini, kampanya yönlendirmesini ve bir kullanıcı dönüşüm gerçekleştirdiğinde sekansı durduran koşulları yönetir. :::note Ayarlar'daki **Adapty entegrasyonu** geçiş düğmesi, sizi Adapty Mail'e giriş yaptıran Adapty iş ortağı çalışma alanıyla *aynı şey değildir*. İş ortağı çalışma alanı, hesabınızı (ve Adapty aracılığıyla kaydolduysanız markanızı) oluşturan şeydir. Buradaki entegrasyon geçiş düğmesi ise etkinlik senkronizasyonunu kontrol eder — her proje için ayrı ayrı açılması gerekir. ::: ## Sorun Giderme \{#troubleshooting\} | Sorun | Çözüm | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | DNS doğrulaması takılı kaldı | Kayıtların tam olarak eşleştiğini kontrol edin — sonda nokta olmamalı, CNAME hedefleri doğru olmalı. 5–10 dakika bekleyin, ardından **Check Verification** düğmesine tekrar tıklayın | | Doğrulama penceresi sona erdi | Kayıtlarınız yerinde duruyor. Yeni bir pencere başlatmak için **Settings → Email Domains** bölümüne alan adınızı tekrar girin | | Oluşturma başarısız oldu veya zaman aşımına uğradı | İnternet bağlantınızı kontrol edip tekrar deneyin. Sorun devam ederse Adapty desteğiyle iletişime geçin | ## Daha fazla bilgi edinin \{#learn-more\} - **[Kullanıcı e-postalarını toplayın](mail-collect-emails)**: Uygulamanız henüz e-posta toplamıyorsa e-posta kapsamı elde etmeye yönelik stratejiler. - **[Gönderme etki alanınızı ayarlayın](mail-sending-domain)**: DNS kayıt ayrıntıları, ısınma kademeleri ve sorun giderme. - **[Ödeme sayfasını ayarlayın](mail-checkout)**: Ödeme hunisi yapısı ve kişiselleştirme. - **[Kampanya analitiği](mail-analytics)**: Teslimat, etkileşim ve geliri takip edin. - **[A/B testi](mail-ab-testing)**: Birden fazla sıra sürümünü test edin. --- # File: mail-collect-emails --- --- title: "Adapty Mail için kullanıcı e-postalarını toplama" description: "Adapty'nin kampanyalarla kullanıcılarınıza ulaşabilmesi için kullanıcı e-postalarını ve sabit tanımlayıcıları iletin." --- Adapty Mail'in kullanıcılara ulaşabilmesi için her kullanıcıya ait sabit bir `customer_user_id` ve bir e-posta adresi gerekir. Bir kampanya başlatmadan önce her ikisini de uygulama kodunuzda ayarlayın. ## Kullanıcı e-postalarını toplama \{#collect-user-emails\} Adapty'ye kullanıcı başına iki değer iletilmesi gerekir: kullanıcıyı tanımlayan sabit bir `customer_user_id` ve e-postanın kendisi. Önce tanımlama yapılmalıdır; aksi takdirde Adapty'nin e-postayı ekleyeceği bir profil olmaz. 1. **Kullanıcıyı tanımlayın.** Sabit bir ID iletin — backend kullanıcı ID'niz, Firebase UID'niz veya benzer bir değer. Bunu SDK başlangıcında `.activate()` fonksiyonuna `customerUserId` olarak geçirebilir ya da daha sonra (örneğin girişte) `Adapty.identify()` çağırabilirsiniz. Her iki durumda da ID, herhangi bir paywall gösterilmeden önce ayarlanmış olmalıdır. Platform kılavuzları: [iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Unity](unity-identifying-users), [Kotlin Multiplatform](kmp-identifying-users), [Capacitor](capacitor-identifying-users). 2. **E-postayı iletin.** Kullanıcı e-posta adresini girer girmez, `email` parametresini kullanarak `updateProfile` aracılığıyla Adapty'e gönderin. Platform kılavuzları: [iOS](setting-user-attributes), [Android](android-setting-user-attributes), [React Native](react-native-setting-user-attributes), [Flutter](flutter-setting-user-attributes), [Unity](unity-setting-user-attributes), [Kotlin Multiplatform](kmp-setting-user-attributes), [Capacitor](capacitor-setting-user-attributes). :::important - Her zaman **kararlı** bir `customer_user_id` kullanın, anonim tanımlayıcı kullanmayın. Kullanıcı uygulamayı kaldırıp yeniden yüklerse, Adapty bu ID'yi kullanarak yeniden yüklemeyi mevcut profile bağlar ve satın almaları doğru kullanıcıya atar. - E-postaları toplayıp Adapty'ye göndermeden önce kullanıcıdan açık onay alın. Hedef pazarlarınızda GDPR, CAN-SPAM ve benzeri düzenlemelere uyum sağlamak sizin sorumluluğunuzdadır. ::: <Details> <summary>E-posta kapsamınızı doğrulayın</summary> Toplamayı uyguladıktan sonra Adapty'de kapsamı kontrol edin: 1. **Müşteriler → Profiller** bölümüne gidin. 2. E-posta adresi eklenmiş profillere göre filtreleyin. Aktif kullanıcılarınızın en az %30-50'sinde e-posta bilgisi bulunduğundan emin olduktan sonra ilk kampanyanızı başlatın. %100'ü beklemenize gerek yok; %30'a ulaşır ulaşmaz başlatabilirsiniz. Daha sonra e-posta adresi ekleyen kullanıcılar, koşulları sağladıklarında aktif kampanyalara otomatik olarak dahil edilir. </Details> ## E-posta toplama stratejileri \{#email-collection-strategies\} Çoğu uygulama varsayılan olarak e-posta toplamaz. Uygulamanızın mevcut durumuna uyan yaklaşımı seçin. | Strateji | En uygun kullanım | Nasıl çalışır | | ---------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | **Mevcut kimlik doğrulama** | Herhangi bir giriş sistemi olan uygulamalar | E-posta zaten elinizde — kullanıcı kimlik doğrulamasından geçtikten sonra Adapty'ye iletin. Nereden okuyacağınızı öğrenmek için aşağıdaki auth yöntemi referansına bakın. | | **Paywall öncesi e-posta kapısı** | Kimlik doğrulaması olmayan uygulamalar — sağlık, wellness, astroloji, fotoğraf editörleri | Onboarding ile paywall arasına tek bir e-posta giriş ekranı ekleyin. Kullanıcılar zaten zaman harcadığından dönüşüm oranı genellikle %70–90 arasında seyreder. | | **Web paywall builder checkout** | Minimal SDK çalışması; e-posta web'de toplanır | Web paywall builder'ın ilk ekranı e-postayı toplar ve Adapty'ye iletir — uygulama içi bir kapı henüz canlıya alınmadan bir kampanyaya tıklayan kullanıcılar için kullanışlıdır. | | **Onboarding adımı** | Quiz tabanlı onboarding (fitness, beslenme, eğitim) | Onboarding'in 2–3. adımına bir e-posta giriş alanı yerleştirin. Bunu değer sunumu olarak çerçeveleyin ("Kişiselleştirilmiş planınızı e-posta ile göndereceğiz") ve adımın atlanabilir olmasından kaçının. | | **Adapty Mail API** | E-postaları Adapty SDK'sı olmadan sunucunuzdan göndermek | Profilleri Adapty Mail API'sinin [Profil kaydet](api-mail/operations/saveProfile) uç noktasına gönderin. Bkz. [Adapty Mail API aracılığıyla e-posta ve işlem gönderme](mail-send-data-via-api). | ## Sınırlamalar \{#limitations\} - **Anonim kullanıcılar**: Sabit bir `customer_user_id` olmayan kullanıcılar kampanya alamaz. Hesap oluştururken veya giriş yaparken bu kullanıcıları tanımlayın — o andan itibaren sağladıkları e-posta, Adapty profilleriyle eşleştirilir. - **E-postası olmayan kullanıcılar**: E-postası bulunmayan profiller kampanya dağıtımının dışında tutulur ve kampanya analizlerinde görünmez. E-posta sağladıkları anda gelecekteki kampanyalara dahil edilirler. --- # File: mail-send-data-via-api --- --- title: "Adapty Mail API aracılığıyla e-posta ve işlem gönderme" description: "Adapty SDK'ya gerek kalmadan kullanıcı profillerini ve işlemleri doğrudan sunucunuzdan Adapty Mail'e gönderin." --- Adapty Mail API, kullanıcı profillerini ve işlemleri Adapty SDK üzerinden yönlendirmeye gerek kalmadan doğrudan sunucunuzdan Adapty Mail'e göndermenizi sağlar. Şu durumlarda kullanabilirsiniz: - Adapty Mail'de henüz bir abone tabanınız yokken abone ekleyin. - Diğer uygulamalarınızdaki abone tabanını yeniden kullanın. - Adapty Mail'i sunucudan sunucuya besleyin; backend'iniz gerçeğin kaynağı olsun. :::note **API mi yoksa SDK mı?** Çoğu uygulama, e-postaları ve satın almaları otomatik olarak toplayan Adapty SDK'sı aracılığıyla Adapty Mail'e veri gönderir. Uygulamanızda Adapty SDK'sı yoksa, veriler zaten sunucunuzda bulunuyorsa veya başka bir kaynaktan abone içe aktarıyorsanız API'yi tercih edin. ::: ## Başlamadan önce \{#before-you-start\} :::warning Veri göndermeden önce Adapty Mail kurulumunu tamamlayın — bu, bir kampanya, segment (gerekiyorsa), web paywall ve başlatılmış bir flow anlamına gelir. Adapty Mail, yalnızca bu kurulum tamamlandıktan sonra oluşturulan profillere e-posta gönderir; daha önce gönderdiğiniz profiller hiçbir e-posta almaz. Önce [Adapty Mail ile başlarken](mail-get-started) adımlarını takip edin, ardından buraya dönün. ::: API anahtarınıza ve temel URL'nize de ihtiyacınız olacak: - **Gizli API anahtarı**: Adapty Mail'de **Settings** bölümüne gidin ve gizli API anahtarınızı kopyalayın. Anahtar projeye özgüdür; bu sayede API hangi projeye ait olduğunu bilir. - **Temel URL**: Tüm istekler `https://api-mail.adapty.io` adresine gönderilir. - **Kimlik doğrulama**: Anahtarı **Authorization** başlığında `Bearer {your_secret_api_key}` biçiminde gönderin. :::important E-postaları toplayıp Adapty Mail'e göndermeden önce kullanıcılardan açık rıza alın. GDPR, CAN-SPAM ve faaliyet gösterdiğiniz pazarlardaki benzer düzenlemelere uyum sağlamak sizin sorumluluğunuzdadır. ::: ## Kullanıcı profilleri gönderme \{#send-user-profiles\} Profil, kullanıcının e-posta adresini ve özelliklerini içerir. Profil oluşturmak veya güncellemek için `/api/v1/profile/save/` adresine POST isteği gönderin. Üç alan zorunludur: - Uygulamanıza veya backend'inize ait sabit bir `external_profile_id` - Adapty Mail'in kampanyaları iletmek için kullandığı `email` - `external_created_at` — segment'lerde kullanabileceğiniz kullanıcı oluşturma zamanı :::important Her zaman sabit bir `external_profile_id` gönderin; anonim veya kuruluma özel bir değer kullanmayın. Adapty Mail, e-postaları, tıklamaları ve satın almaları tek bir profile bağlamak için bu alanı kullanır. ::: ```bash curl --request POST \ --url 'https://api-mail.adapty.io/api/v1/profile/save/' \ --header 'Authorization: Bearer {your_secret_api_key}' \ --header 'Content-Type: application/json' \ --data '{ "external_profile_id": "user_12345", "external_created_at": "2026-06-01T10:30:00Z", "email": "jane@example.com", "country": "US", "custom_attributes": { "plan": "trial" } }' ``` Kullanılabilir her alan için [Profili kaydet](api-mail/operations/saveProfile) referansına bakın. ## İşlem olaylarını gönder \{#send-transaction-events\} :::note **never purchased** flow'unda kullanıcılara ulaşmak için e-posta içeren bir profil yeterlidir. Diğer tüm flow'lardaki kullanıcılar için işlem olayları da gereklidir. ::: **never purchased** dışındaki tüm flow'lar satın alma geçmişiyle çalışır. Satın alma, yenileme ve iptalleri işlerken profil işlem olaylarını gönderin; böylece Adapty Mail kullanıcıyı doğru flow'a yerleştirebilir. İşlem olayları aynı zamanda gelir attribution'ını da destekler. Yalnızca **never purchased** kampanyaları yürütüyorsanız bu adımı atlayabilirsiniz. Bir işlemi kaydetmek için `/api/v1/profile/transaction-event/save/` adresine POST isteği gönderin. Adapty Mail'in işlemi doğru kullanıcıyla ilişkilendirebilmesi için profille birlikte gönderdiğiniz `external_profile_id` değerini kullanın. ```bash curl --request POST \ --url 'https://api-mail.adapty.io/api/v1/profile/transaction-event/save/' \ --header 'Authorization: Bearer {your_secret_api_key}' \ --header 'Content-Type: application/json' \ --data '{ "event_type": "subscription_started", "event_id": "evt_abc123", "event_datetime": "2026-06-10T14:20:05Z", "external_profile_id": "user_12345", "store": "app_store", "store_product_id": "premium_monthly", "store_transaction_id": "1000000123456789", "store_original_transaction_id": "1000000123456789", "purchased_at": "2026-06-10T14:20:00Z", "originally_purchased_at": "2026-06-10T14:20:00Z", "price_usd": "9.99" }' ``` [Save transaction event](api-mail/operations/saveTransactionEvent) referansında mevcut tüm alanları görebilirsiniz. ### Olaylarınızı flow'larla eşleştirin \{#map-your-events-to-flows\} Yaşanan olayı temsil eden `event_type` değerini gönderin. Adapty Mail, profilin durumunu olay geçmişinden çıkarır ve onu uygun flow'a yönlendirir. | `event_type` | Ne zaman gönderilir | Flow | | --- | --- | --- | | `subscription_started` | Bir kullanıcı yeni bir abonelik başlattığında. | Aktif — yeniden etkileşim flow'u yok | | `subscription_renewed` | Bir abonelik otomatik olarak yenilendiğinde. | Aktif — yeniden etkileşim flow'u yok | | `subscription_renewal_reactivated` | Bir kullanıcı otomatik yenilemeyi yeniden açtığında. | Aktif — yeniden etkileşim flow'u yok | | `non_subscription_purchase` | Bir kullanıcı tek seferlik satın alma yaptığında. | Aktif — yeniden etkileşim flow'u yok | | `subscription_renewal_cancelled` | Bir kullanıcı otomatik yenilemeyi kapattığında (süre dolana kadar hâlâ aktif). | Yenileme iptal edildi | | `billing_issue_detected` | Yenileme ödemesi başarısız olduğunda. | Ödeme sorunu | | `entered_grace_period` | Ödeme başarısız olsa da kullanıcı hâlâ ek süre içindeyken. | Ödeme sorunu | | `subscription_expired` | Abonelik sona erip erişim bittiğinde. | Süresi doldu | | `subscription_refunded` | Bir abonelik satın alımı iade edildiğinde. | İade edildi | | `non_subscription_purchase_refunded` | Tek seferlik satın alma iade edildiğinde. | İade edildi | --- # File: mail-brand --- --- title: "Adapty Mail'de Marka" description: "E-posta oluşturma ve web paywallları için kullanılan marka profilini inceleyin ve iyileştirin." --- **Marka**, Adapty Mail'in uygulamanızın kamuya açık kaynaklarından — App Store veya Google Play listesi, açılış sayfası, kullanım koşulları ve gizlilik sayfaları ile sosyal profiller — derlediği bütünleşik bir profildir. E-posta içeriğini, tonunu, görsellerini, web paywall içeriğini ve demoyu bu profil yönetir. Proje başına bir marka tanımlanır; her bir bağımlı özellik aynı profilden okur. Adapty Mail kenar çubuğundaki **Brand** girişinden markayı açın. - **Adapty Mail'e Adapty üzerinden kaydolduysanız**: Markanız, Adapty projenizdeki mağaza URL'sinden otomatik olarak oluşturulmuştur. Brand sayfası, inceleyip düzenlemeye hazır tam profil görünümüyle açılır. - **Bağımsız olarak kaydolduysanız**: Brand sayfası bir kurulum ekranıyla açılır — bkz. [Sıfırdan kurulum](#set-up-from-scratch). ## Marka profilinde neler var \{#whats-in-a-brand-profile\} Bir marka profilinin 13 bölümü vardır. Adapty Mail, bunları doğrudan e-posta ve web paywall oluşturmada kullanır. - **Kimlik**: Uygulama adı, kısa açıklama, slogan. - **Görsel kimlik**: Renkler (birincil, arka plan, ikincil, vurgu, metin, CTA), tipografi, stil notları, logo URL'si. - **Kitle**: Demografik bilgiler, diller, pazarlar. - **Özellikler**: Her özelliğin bir adı, sunduğu fayda ve isteğe bağlı bir açıklaması bulunur. - **İçgörüler**: Benzersiz değer önerisi, gözlemler, sık yapılan itirazlar ve bunlara karşı yanıtlar, etiketler. - **Marka sesi**: Ton, resmiyet düzeyi, kelime dağarcığı, duygusal register. - **Ses örnekleri**: Örnek başlıklar, örnek CTA'lar ve e-posta oluşturma sırasında kullanılan ton önayarları. - **Sosyal kanıt**: Kullanıcı sayısı, puan, puan sayısı, basın haberleri, temel metrikler. - **Sosyal bağlantılar**: Twitter, Instagram, TikTok, YouTube, Facebook, LinkedIn. - **Yasal bağlantılar**: Kullanım koşulları URL'si, gizlilik URL'si, destek e-postası. - **Yorumlar**: Mağaza kaynağından çekilen kullanıcı yorumları — içerik, yazar, puan, kaynak. - **Sorun noktaları**: Yorumlara veya sosyal sinyallere dayanan sorun ifadeleri. - **SSS**: E-posta içeriğinde ve web paywall bölümlerinde kullanılan soru ve cevaplar. ## Bir bölümü manuel olarak düzenleme \{#edit-a-section-manually\} Marka görünümündeki her bölümde bir **Edit** düğmesi bulunur. Bu düğmeye tıklandığında ilgili bölüm için satır içi bir editör açılır. 1. Değiştirmek istediğiniz bölümdeki **Edit** düğmesine tıklayın. 2. Alanları yerinde güncelleyin. Adapty Mail, kaydedilmemiş değişiklikleri taslak olarak takip eder. 3. Değişiklikleri uygulamak için sayfanın üstündeki taslak başlığındaki **Save** düğmesine tıklayın. Değişiklikleri iptal etmek için **Discard** seçeneğine tıklayın. Bir seferde yalnızca bir bölüm açık olabilir. İkinci bir bölüm açmaya çalışırsanız, ilk bölüm sizi işlemi bitirmeye veya iptal etmeye yönlendirir. :::important Bir kaynak işlenirken düzenlemeler duraklatılır — işlenmekte olan bir kaynak, devam eden değişikliklerinizin üzerine yazabilir. İşlem başladığında açık olan tüm düzenleyiciler otomatik olarak kapanır ve işlem tamamlanana kadar taslak bannerındaki **Save** düğmesi devre dışı kalır. ::: ## Yapay Zeka ile İyileştir \{#refine-with-ai\} Sağ alttaki **Refine with AI** düğmesi, markanın yanında bir sohbet paneli açar. Değişiklikleri sade bir dille yazın; yapay zeka size gözden geçirip kaydedebileceğiniz ya da reddedebileceğiniz bir taslak önerir. 1. **Refine with AI** düğmesine tıklayın. 2. Değişikliği açıklayın. Sohbetin kapsamı yalnızca marka düzenlemeleridir — genel sorulara yanıt vermez ve marka profili dışındaki metinleri yeniden yazmaz. 3. Ana görünümde önerilen taslağı inceleyin. Adapty Mail, değişen bölümleri vurgular. 4. Değişiklikleri uygulamak için taslak başlığındaki **Save** düğmesine, kaydedilen markayı korumak için ise **Discard** düğmesine tıklayın. Kullanışlı komut önerileri: - "Tonu daha eğlenceli yap." - "Çevrimdışı mod özelliğini ekle." - "Benzersiz değer önerisini güçlendir." - "Hedef kitle açıklamasını ABD pazarı için yeniden yaz." ## Daha fazla kaynak ekle \{#add-more-sources\} Mağaza kaynağı profili oluşturur. Ek kaynak türleri belirli bölümleri iyileştirir — açılış sayfaları görsel kimliği ve metni, şart ve gizlilik sayfaları yasal bağlantıları, sosyal profiller ise ses örneklerini ve sosyal kanıtı geliştirir. Marka görünümünde **Sources** paneli her kaynağı ve altındaki **Add** formunu listeler. Bir tür seçin, URL'yi yapıştırın ve **Add**'e tıklayın. - **App Store**: `https://apps.apple.com/...` - **Google Play**: `https://play.google.com/store/apps/details?id=...` - **Açılış sayfası**: Pazarlama siteniz, örneğin `https://yourapp.com`. - **Şartlar / Gizlilik**: Şartlar veya gizlilik sayfanıza doğrudan bağlantı. - **Sosyal profil**: Twitter, Instagram, TikTok, YouTube, Facebook veya LinkedIn URL'si. Her türden yalnızca bir kaynak eklenebilir. Bir türdeki kaynak işlem görüyor veya tamamlandıysa seçici o türü devre dışı bırakır. Bir kaynağı değiştirmek için markayı silip yeniden kayıt yaptırmanız gerekir; kaynaklar tek tek kaldırılamaz. ## Sıfırdan Kurulum \{#set-up-from-scratch\} Projenizde henüz bir marka yoksa (genellikle bağımsız Adapty Mail kayıtlarında bu durum yaşanır), **Brand** sayfası bir kurulum ekranıyla açılır. Mağaza kaynağı — App Store veya Google Play — temel taşınızdır; diğer kaynak türleri sonradan eklenebilir. 1. Mağazayı (**App Store** veya **Google Play**) seçin ve listeleme URL'sini yapıştırın. 2. **Build my brand**'e tıklayın. Adapty Mail sayfayı çeker, yorumları ayrıştırır ve marka sesinizi tahmin eder. İşlem genellikle bir dakikadan kısa sürer. 3. İşlem tamamlandığında, 13 bölümün tamamı doldurulmuş şekilde marka görünümü açılır. Bir kaynak başarısız olursa (geçersiz URL, erişilemeyen sayfa, ayrıştırıcı hatası), ekranda hata mesajı ve **Try again** butonu görünür. URL'yi düzeltin ve yeniden gönderin. ## Markanın kullanıldığı yerler \{#where-the-brand-is-used\} Marka, uygulamanızın nasıl göründüğünü ve nasıl bir ses tonu taşıdığını bilmesi gereken tüm alt özellikler tarafından kullanılır: - **E-posta oluşturma**: Metin, ton, görseller, gönderen bloğu ve hero görseli markadan okunur. Bkz. [Kampanya oluşturma](mail-create-campaign). - **Web paywall builder**: Marka, paywall oluşturma için bir ön koşuldur — `brand_saved` olmadan oluşturma işlemi engellenir. Bkz. [Ödeme kurulumu](mail-checkout). - **Onboarding**: Onboarding kontrol listesindeki **Set up brand** adımı, bir marka mevcut olduğunda tamamlandı olarak işaretlenir. ## Bir markayı silme \{#delete-a-brand\} **Delete brand** eylemi, marka görünümünün alt kısmındaki **Danger zone** bölümünde yer alır. 1. Danger zone bölümündeki **Delete** düğmesine tıklayın. 2. İletişim kutusunda onaylayın. Silme işlemi marka profilini ve tüm kaynakları kaldırır. Geri alma seçeneği yoktur — kurtarmak için başlangıç ekranına bir App Store veya Google Play URL'si yapıştırın ve markayı sıfırdan ekleyin. :::warning Mevcut kampanyalar oluşturulduklarında kullanılan marka anlık görüntüsünü korur; ancak siz bir markayı yeniden ekleyene kadar yeni kampanya ve paywall oluşturma işlemleri engellenir. ::: ## Sınırlamalar \{#limitations\} - **Proje başına bir marka**: Her Adapty Mail projesinin tek bir markası vardır. Farklı bir uygulamayı hedeflemek için yeni bir proje oluşturun. - **Tür başına bir kaynak**: Bir markanın en fazla bir App Store, bir Google Play, bir açılış sayfası, bir kullanım koşulları/gizlilik ve bir sosyal profil kaynağı olabilir. - **Kaynak bazında kaldırma yok**: Tek tek kaynaklar arayüzden kaldırılamaz. Bir kaynağın değiştirilmesi gerekiyorsa **Delete brand** seçeneğini kullanın. - **İşlem sırasında düzenleme duraklatılır**: Bir kaynak `pending` veya `processing` durumundayken bölüm düzenlemeleri, iyileştirme sohbeti kaydetme işlemleri ve marka silme işlemleri engellenir. - **Başarısız kaynaklar listede kalır**: `failed` durumundaki bir kaynak, hata mesajıyla birlikte panelde görünmeye devam eder. Yeniden denemek için aynı türü tekrar gönderin; yeni zamanlama başarılı olduğunda başarısız giriş değiştirilir. --- # File: mail-sending-domain --- --- title: "Adapty Mail için gönderim alanınızı ayarlayın" description: "DNS kayıtlarını ekleyin, alan adınızı doğrulayın ve Adapty Mail'in adınıza gönderim yapabilmesi için ısınma sürecini anlayın." --- Adapty Mail, kampanyaları paylaşımlı bir adresten değil kendi alan adınızdan gönderir — böylece gönderici itibarı sizin kontrolünüzde kalır. Bunu bir kez ayarlarsınız ve her kampanya aynı doğrulanmış alan adını kullanır. Minimum adımlar için [Adapty Mail'e Başlarken](mail-get-started#2-set-up-your-sending-domain) sayfasındaki alan adı bölümüne bakın. Bu makale tam kurulumu, doğrulamanın nasıl çalıştığını ve otomatik ısınma davranışını ele almaktadır. ## Gereksinimler \{#requirements\} - **Apex domain**: Kök domaininizi girin (örneğin, `yourapp.com`), alt domain değil. `app.yourapp.com` gibi girişler doğrulama aşamasında reddedilir. - **Aktif NS kayıtları**: Domainin çözümlenebilir olması gerekir. Adapty Mail, kurulum sırasında bir DNS sorgusu yapar ve geçerli NS kayıtları olmayan domainleri reddeder. - **Adapty projesi başına bir domain**: Bir domain, projeler arasında paylaşılamaz. Domain zaten herhangi bir projeye — sizin veya başkasının — kayıtlıysa kurulum başarısız olur. ## Gönderim alan adınızı ayarlayın \{#set-up-your-sending-domain\} Kurulum sihirbazının üç ekranı vardır: alan adını girin, oluşturulan alt alan adlarını onaylayın ve DNS kayıtlarını ekleyin. Her üçü de **Settings → Email Domains** bölümünde yer alır. 1. **Alan adınızı girin.** Apex alan adınızı **Domain** alanına yazın ve **Preview**'e tıklayın. Adapty Mail, biçimi doğrular (ASCII, iki etiket, baş veya sonda kısa çizgi yok, 2+ karakter uzunluğunda TLD) ve DNS'in çözümlendiğini kontrol eder. 2. **Alt alan adlarını onaylayın.** Adapty Mail, sabit öneklerle iki gönderme alt alan adı oluşturur — `mail.yourapp.com` ve `email.yourapp.com` — her birinin kendi SES kimliği vardır. Ayrıca her birinin altında bir Mail-From alt alan adı oluşturur (`hello.mail.yourapp.com` ve `hello.email.yourapp.com`). Bunları inceleyin ve **Confirm**'e tıklayın. 3. **DNS kayıtlarını ekleyin.** Son ekran, eklenecek her kaydı listeler — toplamda 10 kayıt, her gönderme alt alan adı için 5 kayıt ve kökte isteğe bağlı bir DMARC kaydı. Tam listeyi dışa aktarmak için **Download CSV** butonunu kullanın ya da kayıtları tek tek alan adı sağlayıcınıza girin. Kayıtlar yerleştirildikten sonra **Done** butonuna tıklayın. <Details> <summary>DNS kayıt referansı</summary> Her gönderme alt alan adı için (`mail.yourapp.com` ve `email.yourapp.com`) şunları ekleyin: **DKIM — 3 CNAME kaydı.** E-postanın iletim sırasında değiştirilmediğini kanıtlayan kriptografik imzalar. | Alan | Biçim | | ---- | ----------------------------------- | | Tür | CNAME | | Ad | `{token}._domainkey.{subdomain}` | | Değer | `{token}.dkim.amazonses.com` | **Mail-From — 1 MX kaydı.** Hataları yönetir. | Alan | Biçim | | -------- | -------------------------------------------------------- | | Type | MX | | Name | `hello.{subdomain}` (örneğin, `hello.mail.yourapp.com`) | | Priority | `10` | | Value | `feedback-smtp.{region}.amazonses.com` | **SPF — 1 TXT kaydı.** Adapty'nin sizin adınıza e-posta göndermesine izin verir. | Alan | Format | | ----- | -------------------------------------- | | Type | TXT | | Name | `hello.{subdomain}` | | Value | `"v=spf1 include:amazonses.com ~all"` | Kök alan adınıza isteğe bağlı DMARC kaydını ekleyin: | Alan | Format | | ----- | --------------------- | | Type | TXT | | Name | `_dmarc.{domain}` | | Value | `v=DMARC1; p=reject` | Token'lar, bölge ve diğer tüm değerler, kurulum sırasında AWS SES'ten gelir. Bunları her zaman bu referanstan değil, Adapty Mail'deki DNS kayıtları ekranından kopyalayın. </Details> ## Doğrulama nasıl çalışır \{#how-verification-works\} DNS kayıtları eklendikten sonra, Adapty Mail DNS'i otomatik olarak kontrol eder; ayrıca kontrolleri manuel olarak da tetikleyebilirsiniz. - **Otomatik yoklama**: Gönderimin ardından 5 dakika sonra yoklama başlar, ardından her turda iki katına çıkar — 10 dk, 20 dk, 40 dk — ve en fazla 60 dakikada sabitlenir. Kayıtlar bulunana veya 7 günlük süre dolana kadar devam eder. - **Manuel kontrol**: Anlık kontrol başlatmak için **Check Verification** düğmesine tıklayın. Manuel kontroller arasında 60 saniyelik bekleme süresi vardır — çok hızlı tetiklenirse *"Verification check is on cooldown."* hatası döner. - **Durum bilgileri**: Her alt alan adının DKIM ve Mail-From bilgileri bağımsız olarak **Pending**, **Success** veya **Failed** olarak izlenir. Bir alan adı yalnızca dört durum da **Success** gösterdiğinde tamamen doğrulanmış sayılır. - **7 günlük süre sınırı**: Doğrulama 7 gün içinde tamamlanmazsa kimlik **Failed** olarak işaretlenir. DNS kayıtlarınız kayıt kuruluşunuzda kalmaya devam eder; yeni bir süre başlatmak için **Settings → Email Domains** bölümünde alan adını yeniden girin. - **Doğrulamadan sonra**: DNS kayıtlarını daha sonra kaldırır veya değiştirirseniz AWS SES kimliği düşürür. Gönderim yapmayı planladığınız sürece kayıtları yerinde bırakın. - **DNS yayılımı**: Genellikle birkaç dakika sürer; nadir durumlarda 48 saate kadar uzayabilir. ## Alan adı ısınma süreci \{#domain-warm-up\} Gmail veya Yahoo gibi e-posta sağlayıcıları nezdinde yeni alan adlarının henüz bir itibarı olmadığından, taze bir alan adından yüksek hacimli e-posta göndermek iletilerin spam klasörüne düşmesine yol açabilir. Adapty Mail, günlük gönderim limitinizi 14 kademede kademeli olarak artırarak ısınma sürecini otomatik olarak yönetir. Herhangi bir yapılandırma gerekmez. ### Kademeler nasıl çalışır \{#how-tiers-work\} Alan adınız **Kademe 1** (günlük 200 gönderim) ile başlar ve teslimat metrikleri sağlıklı kaldığı sürece otomatik olarak ilerler. Geri dönme oranları veya şikayet oranları yükselirse ilerleme durur; itibar toparlanana kadar geriye de gidebilir. | Katman | Günlük limit | | ------ | ------------ | | 1 | 200 | | 2 | 400 | | 3 | 800 | | 4 | 1.500 | | 5 | 2.500 | | 6 | 4.000 | | 7 | 6.000 | | 8 | 8.000 | | 9 | 10.000 | | 10 | 13.000 | | 11 | 16.000 | | 12 | 20.000 | | 13 | 25.000 | | 14 | 30.000 | Mevcut katmanınız ve günlük limitiniz **Settings → Email Domains** bölümünde görüntülenir. ### Kitle büyüklüğünün lansmana etkisi \{#impact-on-launch-by-audience-size\} | Kitle büyüklüğü | Lansман günündeki etki | | ---------------- | --------------------------------------- | | 200 kullanıcı altı | İlk gün tüm kitleye ulaşılır | | 200–2.000 kullanıcı | Teslimat birkaç güne yayılır | | 2.000+ kullanıcı | Teslimat 1–2 haftaya yayılır | :::tip DNS doğrulaması tamamlanır tamamlanmaz ilk kampanyanızı başlatın. Ne kadar erken göndermeye başlarsanız, alan adınız kademeleri o kadar hızlı geçer ve günlük tam kapasiteye o kadar çabuk ulaşır. ::: ## Sınırlamalar \{#limitations\} - **Proje başına bir domain**: Her Adapty projesinde yalnızca bir gönderici domain kullanılabilir. Farklı bir domaine geçmek için destek ekibiyle iletişime geçin — kontrol panelinde "domain değiştir" seçeneği bulunmamaktadır. - **Projeler arası benzersizlik**: Başka bir projeye kayıtlı bir domain tekrar kullanılamaz. *"Domain is already registered to another project"* hatası görürseniz farklı bir domain seçin ya da destek ekibiyle iletişime geçin. - **Doğrulanmış domainler silinemez**: Herhangi bir alt domain **Success** durumuna ulaştığında kontrol paneli silme işlemini engeller. Beklemedeki domainler silinebilir, ancak DNS kayıtlarını registrar'ınızdan manuel olarak kaldırmanız gerekir. - **Sabit alt domain ön ekleri**: `mail.`, `email.` ve `hello.` Mail-From ön eki sabit olarak tanımlanmıştır — özelleştirilemez. Bu alt domainler DNS'inizde zaten kullanılıyorsa kurulum çakışmayla karşılaşır. - **Yalnızca apex domainler**: Alt domain girişleri, sondaki noktalar ve tek etiketli hostnameler reddedilir. - **Uluslararasılaştırılmış domainler desteklenmez**: Punycode ve IDN desteklenmemektedir. Domain yalnızca ASCII karakterlerden oluşmalıdır. ## Sorun Giderme \{#troubleshooting\} | Sorun | Çözüm | | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | "Enter a valid domain (e.g. example.com)" | Girdiyi kontrol edin: yalnızca apex, yalnızca ASCII, 2+ karakter TLD, başta veya sonda kısa çizgi olmamalı. | | "Domain does not have valid DNS records" | Apex domain'in kendisi çözümlenebilir olmalıdır. Yeniden denemeden önce NS kayıtlarınızın aktif olduğunu doğrulayın. | | "Domain is already registered to another project" | Farklı bir domain seçin ya da kaydın hatalı olduğunu düşünüyorsanız destek ile iletişime geçin. | | "Verification check is on cooldown" | Manuel kontroller arasında 60 saniye bekleyin. Otomatik sorgulama arka planda devam eder. | | Doğrulama Beklemede takılı kaldı | DNS kayıtlarının tam olarak eşleştiğini kontrol edin — sondaki nokta olmamalı, CNAME hedefleri doğru olmalı. DNS yayılımı 48 saate kadar sürebilir. | | "Cannot delete domain: one or more identities have been successfully verified" | Doğrulanmış bir domain kontrol panelinden kaldırılamaz. Yardım için destek ile iletişime geçin. | | E-postalar spam'e düşüyor | DMARC kaydınızın yayınlandığını doğrulayın. Yeni domain'lerin ısınma süresine ihtiyacı vardır — [Domain ısınma](#domain-warm-up) bölümünü inceleyin. | | Yüksek geri dönüş oranı | Kitle listenizin geçerli ve onay vermiş adresler içerdiğini doğrulayın. Geri dönüşler, kademe ilerlemesini yavaşlatır veya durdurur. | --- # File: mail-checkout --- --- title: "Adapty Mail için ödeme sayfasını ayarlama" description: "Web paywallı oluşturun ve e-posta kampanyalarınıza kişiselleştirilmiş bir web ödeme sayfası sunmak için bir ödeme sağlayıcısı bağlayın." --- Adapty Mail'in gönderdiği her e-posta, o alıcıya özel benzersiz bir ödeme bağlantısı içerir. Bağlantıya tıkladıklarında, kullanıcıyı profiliyle tanımlayan, teklifinizi sunan ve ödemeyi işleyen bir web ödeme sayfasına yönlendirilirler. Ödeme sayfaları, Adapty Mail içindeki **Web Paywalls** bölümünde yer alır ve dahili **web paywall builder** ile düzenlenir. ## Gereksinimler \{#requirements\} - Abonelik ürünlerinizin yapılandırıldığı bir web ödeme sağlayıcısı. **Generate with AI** yalnızca Stripe'ı destekler ve bağlantı builder içinde kurulur. **Use your own hosted paywall** ise ödeme sizin tarafınızda işlendiğinden Stripe, Paddle, PayPal veya başka herhangi bir sağlayıcıyı kabul eder. Web paywall builder için ayrı bir hesaba ihtiyacınız yok. Adapty Mail ile birlikte gelir: ilk giriş yaptığınızda çalışma alanı otomatik olarak oluşturulur ve editöre Adapty kimlik bilgilerinizle giriş yaparsınız. Bu, ana Adapty kontrol panelinin paywall sayfasında yapılandırmış olabileceğiniz web paywalllarından bağımsızdır — Adapty Mail'in web paywallları ayrı birer varlıktır ve tamamen Adapty Mail üzerinden yönetilir. ## Ödeme dönüşüm huninizi oluşturun \{#set-up-your-checkout-funnel\} Adapty Mail'de **Web Paywalls → Create** bölümüne gidin. İki seçeneğiniz var: - **Generate with AI**: Adapty Mail'in yerleşik web paywall oluşturucusu huniyi sizin için hazırlar. Yalnızca Stripe desteklenir — Paddle veya PayPal için ikinci seçeneği kullanın. - **Use your own hosted paywall**: Herhangi bir ödeme sağlayıcısıyla kendi barındırdığınız bir paywallı bağlayın. ### Yapay Zeka ile Oluştur \{#generate-with-ai\} Oluştur sayfası en üstte bir **Prerequisites** paneli gösterir; bu panel, her ön koşul için satır içi eylem düğmeleri içerir — marka hazırlığı, builder girişi, Stripe bağlantısı, ürünler ve son olarak inceleme-yayınlama adımı. Paneli tamamlayın; her adım tamamlandığında panel yenilenir. Ön koşullar yeşile döndüğünde, oluşturma iletişim kutusunu açmak için **Generate** düğmesine tıklayın. İki seçim yapmanız gerekir: - **Environment**: **Production** veya **Sandbox** seçin. Sandbox, Stripe test modu ürünlerinizi kullanır ve geliştirme ile yerel ortamlar için güvenli varsayılan seçenektir — hesabı production'dan izole edilmiştir, bu nedenle test işlemleri canlı verileri etkilemez. - **Plans**: En fazla **3 Stripe planı** seçin. Her plan, bir ürün + fiyat kombinasyonudur. Paywall bu planları ödeme sırasında teklifler olarak sunar. 3'ten az seçerseniz, paywall yalnızca seçtiğiniz planları gösterir. **Generate** butonuna tıklayarak derlemeyi başlatın. Tamamlandığında, sonucu incelemek ve yayımlamak için builder'daki editörü açın. Ardından **Save** butonuna tıklayın. :::important Paywall, ödeme trafiğine hizmet verebilmesi için yayımlanmış olmalıdır. Yayımlanmamış paywalllar, kullanıcılar e-posta ödeme bağlantılarına tıkladığında hata döndürür. ::: Ödeme sağlayıcı ayrıntıları için builder içindeki bilgiler (Stripe hesapları, test ve canlı mod, ürün kurulumu) hakkında [Web paywall yapılandırması](web-paywall-configuration) sayfasına bakın. ### Kendi barındırdığınız paywalli kullanın \{#use-your-own-hosted-paywall\} 1. Create sayfasında **Enter URL manually** seçeneğini belirleyin. 2. Barındırdığınız paywall URL'sini yapıştırın. URL'nin sorgu parametresi olarak `{email}` ve `{external_profile_id}` yer tutucularını içermesi gerekir — Adapty Mail bunları her alıcı için ayrı ayrı doldurur, böylece sayfa ziyaretçinin kim olduğunu bilir. Örnek: ``` https://example.com/paywall?email={email}&profile={external_profile_id} ``` 3. Kaydedin. Bu yöntem herhangi bir ödeme sağlayıcısıyla çalışır — Adapty Mail yalnızca yönlendirme ve parametre değiştirmeyi üstlenir; ödeme ve kişiselleştirme tamamen sizin tarafınızda gerçekleşir. ## Ödeme sayfası nasıl görünür \{#what-the-checkout-looks-like\} Kullanıcı bir ödeme bağlantısına tıkladığında **Ana dönüşüm sayfasına** yönlendirilir. Ödeme girişiminin ardından **Ödeme başarılı** veya **Ödeme başarısız** sayfalarından biri gösterilir; her girişimde yalnızca biri görünür. **Ana dönüşüm sayfası** Tam sayfa satış sunumu. Yapay zeka her bölüm için metni ve görselleri otomatik olarak oluşturur: | Bölüm | Yapay Zekanın Ürettiği İçerik | |---|---| | Başlık | Kalın, faydaya odaklı başlık | | Alt başlık | Destekleyici değer önerisi | | Teklif rozeti | Aciliyet rozeti (uydurma fiyat yok — belirsiz promosyon dili kullanır) | | CTA butonu | Eyleme yönlendiren metin, 2–5 kelime | | Faydalar | 3–6 emoji + metin fayda kartı | | Özellikler | Başlık ve alt başlıkla 3–8 özellik açıklaması | | Planlar | Plan seçim başlığı ve teklif sayacı metni | | Sosyal kanıt | Topluluk kanıt metni ve 3–5 gerçekçi kullanıcı yorumu | | SSS | 3–6 sık sorulan soru ve yanıtı | | Güvence | Para iade veya memnuniyet garantisi metni | **Ödeme başarılı** Sonraki adımları içeren kutlama mesajı ve yapay zeka tarafından oluşturulmuş bir görsel. **Ödeme başarısız** Kullanıcıyı tekrar denemesi için yönlendiren samimi bir mesaj. Ödeme durumu korunur. ## Kişiselleştirme nasıl çalışır \{#how-personalization-works\} Her e-posta, alıcının `customer_user_id` ve e-posta adresinin parametre olarak eklendiği benzersiz bir ödeme URL'si içerir: ``` https://your-funnel.com/?cid={{customer_user_id}}&email={{email}} ``` Adapty bu URL'leri her e-posta gönderiminde otomatik olarak oluşturur — web paywall builder'da herhangi bir yapılandırma gerekmez. Kullanıcı tıkladığında builder, kimliğini belirlemek için parametreleri okur. Satın alma tamamlandığında Adapty, geliri dönüşümü sağlayan belirli e-postayla eşleştirir. Bu veriler [Kampanya analizleri](mail-analytics) sayfasında görüntülenir. ## Sorun Giderme \{#troubleshooting\} | Sorun | Çözüm | |---|---| | Ödeme bağlantısı açılmıyor | Paywallın web paywall builder'da yayınlandığını doğrulayın | | Ödeme sırasında kullanıcı tanımlanamıyor | E-posta gönderilmeden önce doğru kullanıcı kimliğiyle `Adapty.identify()` çağrıldığını kontrol edin | | Satın alma e-postaya atfedilemiyor | Ödeme URL'sinde `cid` parametresinin bulunup bulunmadığını kontrol edin — parametreler eksikse desteğe başvurun | --- # File: mail-email-campaigns --- --- title: "Adapty Mail'de e-posta kampanyaları" description: "Çok e-postalı diziler tasarlayın, doğru tonu seçin ve doğru kullanıcıları hedefleyin." --- Adapty Mail'deki bir kampanya; metinler, tasarım, ana görseller ve gecikmeler dahil olmak üzere uygulamanız için tek seferde oluşturulan eksiksiz bir çok e-postalı dizidir. Kampanya tek başına e-posta göndermez: **taslak** olarak kaydedilir ve yalnızca bir [flow](mail-create-flow)'a bağlandığında iletilmeye başlar; flow ise kampanyayı bir tetikleyici ve kitleyle ilişkilendirir. Kampanya oluşturmak, doğru tonu seçmek ve doğru kullanıcıları hedeflemek için aşağıdaki kılavuzları kullanın. <CustomDocCardList ids={['mail-create-campaign', 'mail-suppression']} /> --- # File: mail-create-campaign --- --- title: "Adapty Mail'de kampanya oluşturma" description: "Uygulamanızın mağaza meta verilerinden eksiksiz bir e-posta dizisi oluşturun ve bir akışa eklemeden önce düzenleyin." --- Adapty Mail, uygulamanızın mağaza meta verilerinden tam bir e-posta dizisi oluşturur — metin, tasarım, hero görseller, konu satırları ve gecikmeler dahil. Metin yazarlığı veya tasarım çalışması gerekmez. Kampanya taslak olarak kaydedilir; yalnızca bir [akışa](mail-create-flow) bağladığınızda iletilmeye başlar. ## Başlamadan önce \{#before-you-start\} - **Kaydedilmiş web paywall'u**: Her kampanya bir web paywall'una bağlı olmalıdır. Backend, web paywall'u olmayan kampanyaları reddeder. Henüz bir paywall'unuz yoksa bkz. [Web paywall oluşturma](mail-get-started#4-create-a-web-paywall). - **Settings'te App Store veya Google Play URL'si**: Yapay zeka, sekansı özelleştirmek için bu URL'den uygulama meta verilerini (ad, kategori, açıklama, ekran görüntüleri) okur. Ayarlı değilse **Settings → App metadata** bölümünden ekleyin. ## 1. Sıralamayı oluşturun \{#generate-the-sequence\} 1. Adapty Mail'de **Campaigns** bölümüne gidin ve **Create** düğmesine tıklayın. 2. Kampanya adını belirleyin. 3. **Web paywall** açılır menüsünden e-postaların bağlantı vereceği web paywall'u seçin. 4. **E-posta oluştur**'a tıklayın. 5. Oluşturma iletişim kutusunu doldurun: - **Tone**: Listeden seçin. Seçenekler, uygulamanızın kategorisine özel olarak oluşturulur — farklı bir uygulama farklı seçenekler görür. Seçiminiz, her e-postadaki konu satırlarını, başlıkları, gövde metnini ve CTA'ları şekillendirir; düzeni veya hero görselleri etkilemez. - **Language**: E-posta dilini seçin. - **Custom prompt** (isteğe bağlı): 2.000 karaktere kadar serbest biçimli talimatlar. Bir promosyonu, özel bir günü, kitle nüansını, mutlaka eklenmesi gereken noktaları veya hazır seçeneklerin yansıtamadığı ek ton yönlendirmesini belirtmek için kullanın. - **Number of emails**: Varsayılan olarak yapay zeka, en iyi uygulamalara ve uygulama bağlamınıza göre sayıyı belirler. Kendiniz ayarlamak isterseniz **Set number manually**'ye tıklayın ve bir değer seçin (**1–15**, varsayılan **4**). **Oluştur**'a tıkladığınızda ton o kampanyaya kilitlenir. Farklı bir ton denemek için yeni bir kampanya oluşturun; her oluşturma işlemi farklı bir seçenek karışımı sunabilir. 6. **Oluştur**'a tıklayın. Oluşturma işlemi genellikle birkaç dakika sürer. Tamamlanamazsa arka uç 5 dakika sonra zaman aşımına uğrar — bu durumda tekrar deneyin. ## 2. İncele ve düzenle \{#review-and-refine\} Oluşturma işleminin ardından tam sıra bir önizlemede gösterilir. Her e-posta için şunları görebilirsiniz: - **Konu satırı varyantları**: E-posta başına üç konu seçeneği. Adapty Mail bunları teslimat sırasında test eder ve en iyi performans göstereni göndermeye devam eder — bkz. [A/B testi](mail-ab-testing). - **Başlık, gövde metni ve CTA**: Ana içerik bloğu. - **Hero görseli**: E-postanın içeriğine ve markanıza uygun oluşturulmuş bir görsel. - **Düzen ve gecikme**: E-postanın nasıl düzenlendiği ve bir önceki e-postadan ne kadar süre sonra gönderileceği. Önizleme başlığında bir **Tema değiştirici** (Otomatik, Aydınlık, Koyu) bulunur — önizleme bölmesinin sağ üst köşesindeki simge düğmeleri. Bu yalnızca önizlemenin nasıl görüntüleneceğini etkiler; oluşturulan içerik tüm modlarda aynıdır. Yeniden oluşturmak zorunda kalmadan her e-postanın her renk şemasında nasıl göründüğünü kontrol etmek için kullanabilirsiniz. Şunları yapabilirsiniz: - **Bireysel e-postaları yeniden oluştur**: Yapay zeka, tek bir e-postanın metnini ve yeni bir hero görselini yeniden yazar. Konum, zamanlama ve genel tasarım sistemi (renkler, tipografi, karanlık mod) aynı kalır; yalnızca hedeflenen e-posta değişir. - **HTML'i doğrudan düzenle**: Yapay zekanın tam olarak yapamadığı şeyler üzerinde ayrıntılı kontrol için bir HTML kod editörü açılır. :::note E-postalar otomatik olarak uyum sağlar. Çok sütunlu tasarımlar 620 px'in altındaki ekranlarda tek sütuna düşer ve her düzen; Gmail (web ve mobil), Apple Mail (macOS ve iOS), Outlook masaüstü, Yahoo Mail ve Samsung Mail'de — hem açık hem koyu modda — test edilmiştir. ::: ## 3. Taslak olarak kaydedin \{#save-as-a-draft\} Kampanyayı taslak olarak kaydetmek için **Create** düğmesine tıklayın. Henüz hiçbir e-posta gönderilmez — kampanya düzenleyicisinde ayrı bir "yayınla" veya "başlat" işlemi yoktur. Bir kampanyanın durumu, aktif bir akışa bağlı olup olmadığını yansıtır: - **draft**: Herhangi bir akışa bağlı değil. - **live**: Bir akışa bağlı ve şu anda kullanıcıları yönlendiriyor. - **inactive**: Daha önce bağlıydı, ancak akışın A/B testi sarmalayıcısı tamamlandı. - **archived**: Kontrol panelinden silindi. :::important Taslak bir kampanya kendi başına hiçbir zaman gönderim yapmaz. E-posta iletimini başlatmak için şunlardan birini yapmanız gerekir: - Kampanyayı doğrudan bir [akışa](mail-create-flow) ekleyin ya da - Bir [A/B testine](mail-ab-testing) dahil edip A/B testini bir akışa ekleyin. Bunlardan biri gerçekleşene kadar kampanya `draft` (taslak) durumunda kalır ve hiçbir alıcıya ulaşılmaz. ::: --- # File: mail-suppression --- --- title: "Adapty Mail'de abonelik iptali ve engelleme" description: "Adapty Mail'in kullanıcılara gönderimi nasıl durdurduğu — abonelik iptali, SES geri dönüşleri, şikayetler ve durdurma koşulu mekanizması." --- Adapty Mail, bir kullanıcıya gönderimi iki farklı koşulda durdurur: - **Engelleme**: Kullanıcı, bu projedeki gelecekteki tüm gönderimlerden hariç tutulur (abonelik iptali, geri dönüş, şikayet, red veya kısıtlama). - **Durdurma koşulu**: Kullanıcı dönüşüm gerçekleştirdiğinde mevcut dizisi iptal edilir. Kullanıcı engellenmez ve diğer kampanyalar için uygun olmaya devam eder. Her iki mekanizma da proje bazında çalışır. Bir Adapty projesindeki engelleme, diğerini etkilemez. ## Abonelik iptali \{#unsubscribe\} Adapty Mail'in gönderdiği her e-postanın alt bilgisinde bir abonelik iptali bağlantısı bulunur. 1. Kullanıcı bağlantıya tıklar. Adapty Mail bir onay sayfası açar. 2. Kullanıcı onaylar. Arka uç, profili `suppression_reason = 'unsubscribe'` olarak işaretler, kalan diziyi iptal eder ve profili projedeki gelecekteki gönderimlerden hariç tutar. Abonelik iptali URL'sindeki token, `profile_id` ve `scheduled_email_id` bilgilerini içerir; bu nedenle giriş yapılması gerekmez. :::note Adapty Mail ayrıca her e-postayla birlikte `List-Unsubscribe: <URL>, <mailto:>` başlığını ve `List-Unsubscribe-Post: List-Unsubscribe=One-Click` başlığını gönderir. Gmail ve Yahoo, toplu göndericiler için bunu zorunlu kılar (RFC 8058). Bu başlığı destekleyen istemciler, gelen kutusundan doğrudan tek tıkla abonelik iptali düğmesi sunar — onay sayfası gerekmez. ::: ## Otomatik engelleme \{#automatic-suppression\} Adapty Mail, AWS SES teslimat olaylarını SNS aracılığıyla dinler ve aşağıdaki olaylardan herhangi birinde kullanıcıyı hemen engeller: | Olay | Neden kodu | Ne anlama gelir | | ---------- | ----------- | --------------------------------------------------------------------------------------- | | Geri dönüş | `bounce` | E-posta adresi geçersiz, posta kutusu dolu veya alan adı mevcut değil. | | Şikayet | `complaint` | Kullanıcı e-postayı spam olarak işaretledi. | | Red | `reject` | SES mesajı göndermeden önce reddetti. | | Kısıtlama | `throttle` | Gönderim hızı alan adı güvenlik limitlerini aştı. | Her olay için sonuç aynıdır: kullanıcı engelleme listesine eklenir, kalan dizi iptal edilir ve kullanıcı projedeki gelecekteki gönderimlerden hariç tutulur. :::important Adapty Mail, kalıcı ve geçici geri dönüşleri **birbirinden ayırt etmez**. Dolu bir posta kutusu gibi geçici koşullar dahil her türlü geri dönüş, kullanıcıyı hemen engeller. Yeniden deneme penceresi yoktur. ::: ## Durdurma koşulu \{#stop-condition\} Bir kullanıcı dizinin ortasında dönüşüm gerçekleştirdiğinde, Adapty Mail kalan e-postalarını `stop_condition` nedeniyle iptal eder. Dönüşüm, kullanıcının abonelik durumunun **Subscribed** (Abone olundu) veya tek seferlik satın alma durumunun **Purchased** (Satın alındı) olarak güncellenmesi anlamına gelir. Durdurma koşulu, engellemeden farklıdır: - **Engelleme**: Kullanıcıyı projedeki tüm gelecekteki gönderimlerden hariç tutar. - **Durdurma koşulu**: Yalnızca mevcut diziyi iptal eder. Kullanıcı diğer kampanyalar için uygun olmaya devam eder — örneğin aktif aboneleri hedefleyen bir yenileme veya geri kazanma flow'u. Durdurma koşulu iptalleri, kampanya analizlerinde engellemelerle birlikte görünür. ## Engellemeyi yönetme \{#managing-suppression\} Adapty Mail'in engellenen kullanıcıları görüntülemek veya kaldırmak için kontrol paneli arayüzü yoktur. Bir profili engellemeden çıkarmak için — örneğin, yanlışlıkla bir test e-postasını spam olarak işaretleyen biri — Adapty destek ekibiyle iletişime geçin. ## Adapty Mail'in uyumluluk açısından yönettiği konular \{#what-adapty-mail-handles-for-compliance\} Adapty Mail şunlarla birlikte gelir: - **Abonelik iptali bağlantısı**: Her e-postanın alt bilgisine eklenir, kullanıcı onayladıktan hemen sonra işleme alınır. - **List-Unsubscribe başlıkları**: Gelen kutusundan tek tıkla abonelik iptali için her e-postayla gönderilir (RFC 8058). - **Otomatik engelleme**: SES geri dönüşü, şikayet, red ve kısıtlama olaylarında tetiklenir. Sizin sorumluluğunuzda olan kısımlar: - **Fiziksel posta adresi**: CAN-SPAM, e-postanın alt bilgisinde bir adres bulunmasını zorunlu kılar. Adapty Mail bunu otomatik eklemez — kampanya tasarımınıza kendiniz ekleyin. - **Açık katılım onayı**: Kullanıcının e-posta adresini Adapty'ye iletmeden önce bunu toplayın. Bkz. [Kullanıcı e-postalarını toplama](mail-collect-emails). - **GDPR silme talepleri**: Adapty Mail, "verilerimi sil" uç noktası sunmaz. Bir kullanıcı silme hakkını kullanırsa Adapty destek ekibiyle koordineli şekilde hareket edin. --- # File: mail-flows --- --- title: "Adapty Mail'de Flow'lar" description: "Flow'ların kampanyaları doğru kullanıcılara doğru anda nasıl yönlendirdiği — tetikleyiciler, segmentler ve öncelik kuralları." --- <CustomDocCardList ids={['mail-create-flow']} /> Bir **flow**, kaydedilmiş bir kampanyayı zamanlanmış gönderilere dönüştürür. Bir tetikleyici olayı (kullanıcının abonelik durumu), bir segmenti (hangi kullanıcıların uygun olduğu) ve kullanıcıların alacağı kampanyayı birbirine bağlar. Adapty Mail, eşleşen bir olay tetiklendiğinde her flow'u değerlendirir — yoklama yok, cron yok, manuel başlatma yok. ## Tetikleyiciler \{#triggers\} Adapty Mail, beş sabit tetikleyiciyle gelir; her birinin **Flows** altında kendi flow görünümü vardır: - **Never purchased**: Kayıt olmuş ancak henüz satın alma yapmamış kullanıcılar. Amaç: aktivasyon ve ilk dönüşüm. Deneme kullanıcıları burada yer almaz — deneme başlatmak aktif abonelik sayılır. - **Renewal cancelled**: Otomatik yenilemeyi kapatan ancak hâlâ aktif aboneliği olan kullanıcılar. Dönüşüm öncesinde iptal eden ücretli aboneleri ve deneme kullanıcılarını kapsar. Onları kurtarmak için en güçlü pencere — hâlâ erişimleri var. Mesajın farklılaşması gerekiyorsa segment filtreleriyle ücretli ve deneme kitlelerini ayırın. - **Billing issue**: Ödeme başarısız oldu — reddedilen veya süresi dolmuş kart ya da kaçırılan yenilemeden sonra ek süre. Amaç: acil, yardımsever bir kurtarma, satış baskısı değil. Onları hızla geri kazanın — zaten ödeme yapmak istiyorlardı. - **Expired**: Abonelik sona erdi ve erişim ortadan kalktı. Hem ücretli aboneliklerin sona ermesini hem de dönüşüm olmadan biten denemeleri kapsar. Amaç: onları geri kazanmak. Segment filtreleri, deneme süresi dolmuş ve ücretli aboneliği sona ermiş kitleler için içeriği özelleştirebilir. - **Refunded**: Satın alma sonrası iade talep eden kullanıcılar. Amaç: neyin yanlış gittiğini anlamak ve daha uygun bir seçenek sunmak. Ton alçakgönüllü ve meraklı olmalı, sert bir satış girişimi değil. Tetikleyiciler yapılandırılamaz — özel tetikleyici oluşturamazsınız ya da listeyi genişletemezsiniz. ## Tüm Kullanıcılar segmenti \{#the-all-users-segment\} Adapty Mail, filtresi olmayan yerleşik bir **All Users** segmentiyle gelir — projedeki her kullanıcı bu segmente girer. Flow'larda en çok, daha spesifik bir segmentle eşleşmeyen herkese hizmet eden bir yakalama satırı olarak kullanışlıdır. All Users düzenlenemez veya silinemez. Ayrıntılı bilgi için [Segments](mail-segments) bölümüne bakın. ## Öncelik \{#priority\} Her tetikleyici görünümü, önceliğe göre sıralanmış **segment → kampanya** (veya segment → A/B testi) satırlarından oluşan bir liste içerir. Bir kullanıcı tetikleyiciyi çalıştırdığında Adapty Mail şunları yapar: 1. Satırları yukarıdan aşağıya doğru tarar. 2. Segmentin eşleştiği ilk satırdaki kampanyayı gönderir. 3. Durur. Sonraki satırlar o kullanıcı için değerlendirilmez. Sıralama önemlidir. Daha dar bir satırın üstüne yerleştirilen geniş kapsamlı bir segment, dar satırla eşleşecek her kullanıcıyı emer. Yeniden sıralamak için herhangi bir satırın solundaki tutamacı sürükleyin — arka uç, kaydedilen sıraya göre 1, 2, 3… öncelik numaralarını yeniden atar. :::important **All Users** satırı varsa en sona (en düşük önceliğe) yerleştirilmelidir. Arka uç, All Users son slotta değilse kaydetmeyi reddeder — aksi takdirde daha spesifik segmentlerin eşleşme şansı bulmadan her kullanıcıyı emer. ::: ## İçerik türleri \{#content-types\} Bir satır tek bir kampanya veya A/B testi sunabilir: - **Campaign**: Segmentle eşleşen herkese tek bir kampanya gönderir. - **A/B Test**: İki veya daha fazla kampanyayı yapılandırılabilir ağırlıklarla sarar, gelen kullanıcıları aralarında rastgele dağıtır ve varyant bazında metrikleri takip eder. Bkz. [A/B testing](mail-ab-testing). ## Yaşam döngüsü \{#lifecycle\} Flow satırlarının taslak durumu yoktur. Bir satır, kaydettiğiniz andan itibaren canlıya geçer — o andan itibaren tetikleyiciyi çalıştıran ve segmentle eşleşen kullanıcılar kampanyaya yönlendirilir. - **Satır oluşturma**: Kaydedildiğinde hemen gönderime başlar. - **Satır düzenleme**: Değişiklik, o andan itibaren tetikleyiciyi çalıştıran kullanıcılara uygulanır. Sıra ortasındaki kullanıcılar önceki yapılandırmayla devam eder. - **Satır silme**: Yeni kullanıcılar sıraya girmeyi bırakır. Sıra ortasındaki kullanıcılar zamanlanmış e-postalarını almaya devam edebilir — otomatik iptal yoktur. A/B testi satırları, satırın kendisinden bağımsız olarak kontrol edilen kendi yaşam döngülerine (**taslak → canlı → tamamlandı**) sahiptir. Bkz. [A/B testing](mail-ab-testing). --- # File: mail-create-flow --- --- title: "Adapty Mail'de flow satırları oluşturma ve yönetme" description: "Kampanyaları kullanıcılarınıza yönlendirmek için bir flow'a satır ekleyin, yeniden sıralayın, düzenleyin ve silin." --- Her [flow](mail-flows), sabit bir tetikleyici görünümündeki önceliklendirilmiş **segment → kampanya** satırlarından oluşur. Bu kılavuz, bu satırları nasıl ekleyeceğinizi, yeniden sıralayacağınızı, düzenleyeceğinizi ve sileceğinizi açıklar. Tetikleyiciler, öncelikler ve içerik türleri hakkındaki kavramsal bilgiler için [Flow'lar](mail-flows) sayfasına bakın. ## Satır ekleme \{#add-a-row\} 1. Adapty Mail'de **Flows** bölümüne gidin ve yapılandırmak istediğiniz tetikleyiciyi açın. 2. Diyaloğu açmak için **Create**'e tıklayın. 3. Diyalogda: - **Segment**: Bir segment seçin ya da herkesi kapsayan **All Users** seçeneğini kullanın. - **Content type**: Tek bir kampanya için **Campaign**, birden fazlasını karşılaştırmak için **A/B Test** — bkz. [A/B testi](mail-ab-testing). - **Campaign**: Göndermek istediğiniz kampanyayı seçin. 4. **Save**'e tıklayın. Satır hemen aktif olur. Tetikleyiciyi geçen ve segmentle eşleşen kullanıcılar o andan itibaren kampanyayı almaya başlar. ## Satırları yeniden sıralama \{#reorder-rows\} Önceliği değiştirmek için bir satırın solundaki tutamacı sürükleyin. Adapty Mail, kaydedilen sıraya göre `priority: 1, 2, 3…` değerlerini otomatik olarak atar. **All Users** satırı her zaman en son slotta kalmalıdır — onu başka bir satırın üzerine sürüklemek kayıt sırasında engellenir. ## Satır düzenleme \{#edit-a-row\} Mevcut değerlerin önceden dolu olduğu diyaloğu yeniden açmak için bir satırdaki **Change content**'e tıklayın. Segment, içerik türü ve kampanyayı değiştirip **Save**'e tıklayarak uygulayabilirsiniz. A/B testi kullanan bir satır yalnızca test **draft** (taslak) durumundayken düzenlenebilir. Test başlatıldıktan sonra, testi bitirene kadar içeriği kilitlenir. ## Satır silme \{#delete-a-row\} Satırın eylemler menüsünü açın ve **Delete**'e tıklayın. Onay diyaloğu yoktur — satır hemen kaldırılır. - **Kampanya satırları**: Her zaman silinebilir. - **Canlı A/B testi olan satırlar**: Silinemez. Önce **Finish A/B test** seçeneğini kullanarak testi bitirin, ardından satırı silin. :::note Bir satırı silmek, yeni kullanıcıların diziye girmesini durdurur. Diziyi zaten yarıda bırakan kullanıcılar zamanlanmış e-postalarını almaya devam edebilir — otomatik bir iptal işlemi gerçekleşmez. ::: --- # File: mail-segments --- --- title: "Adapty Mail'de Segmentler" description: "Profil ve satın alma verilerine dayalı yeniden kullanılabilir kitle dilimleri oluşturarak flow'ları ve A/B testlerini hedefleyin." --- **Segment**, yeniden kullanılabilir bir kitle dilimidir. Bir kez **Segments** bölümünde tanımlarsınız, ardından flow'lardan ve A/B testlerinden buna başvurursunuz. Segmentler filtre tanımlarıdır, anlık görüntü değil: bir flow tetikleyicisi çalıştığında talep üzerine değerlendirilirler; bu nedenle üyelik her zaman en güncel profil verilerini yansıtır. ## Segment oluşturma \{#create-a-segment\} 1. Adapty Mail'de **Segments** bölümüne gidin ve **+ Create** düğmesine tıklayın. **New Segment** başlıklı oluşturma sayfası açılır. 2. Segment için bir **Name** (zorunlu) ve isteğe bağlı bir **Description** girin. 3. **Filters** altında, eklemek istediğiniz her [kural](#available-filter-fields) için **Add filter** düğmesine tıklayın. Her filtre, **Filter 1**, **Filter 2** gibi etiketlerle daraltılabilir bir kart olarak görünür. 4. Her filtre için bir alan seçin, bir operatör belirleyin ve karşılaştırma değerini girin. 5. Segmenti kaydedin. :::important Filtreler **AND** (VE) mantığıyla birleştirilir — bir kullanıcının segmentte yer alabilmesi için tüm filtreleri karşılaması gerekir. OR (VEYA) mantığı ve iç içe gruplar desteklenmez. Her alan bir segmentte yalnızca bir kez kullanılabilir; aynı alanı birden fazla değerle karşılaştırmanız gerekiyorsa mantığı ayrı segmentlere bölün. ::: ## Adapty'den bir segment içe aktarma \{#import-a-segment-from-adapty\} Filtrelerden sıfırdan segment oluşturmak yerine, ana Adapty Kontrol Paneli'nden mevcut bir kitle segmentini içe aktarabilirsiniz. 1. **Segments** sayfasında **Import** düğmesine tıklayın. 2. Listeyi inceleyin. **Importable segments** onay kutusu ve filtre koşullarıyla birlikte gösterilir. **İçe aktarılamayan** segmentler; desteklenmeyen alan (örneğin Apple Ads attribution verisi), desteklenmeyen operatör veya Adapty Mail'de karşılığı olmayan abonelik durumu gibi belirli bir nedenle soluk renkte görünür. 3. İstediğiniz segmentleri işaretleyip **Import** düğmesine tıklayın. :::important İçe aktarma işlemi, segment filtrelerinin o anki bağımsız bir kopyasını oluşturur — orijinal Adapty segmentiyle senkronize tutulmaz ve Adapty Mail tekrar eden kayıtları tespit etmediğinden, aynı segmenti tekrar içe aktarmak her seferinde ayrı bir kopya oluşturur. ::: İçe aktarılan segmentler, elle oluşturduğunuz segmentlerde olduğu gibi **Draft** durumuyla başlar; böylece filtrelerini hemen düzenleyebilirsiniz. ## Kullanılabilir filtre alanları \{#available-filter-fields\} | Grup | Alan | Tür | | -------------- | --------------------------------- | ------- | | Profil | E-posta | String | | Profil | Yaş | Integer | | Profil | Ülke | String | | Profil | Harici profil ID | String | | Profil | Oluşturulma tarihi | Date | | Satın alma durumu | Toplam gelir (USD) | Decimal | | Satın alma durumu | Abonelik durumu | Enum | | Satın alma durumu | Abonelik satın alma tarihi | Date | | Satın alma durumu | Abonelik bitiş tarihi | Date | | Satın alma durumu | Tek seferlik satın alma durumu | Enum | | Satın alma durumu | Tek seferlik satın alma tarihi | Date | **Abonelik durumu değerleri**: Hiç satın alınmadı, Abone olundu, Otomatik yenileme kapalı, Ödeme sorunu, Ek süre, Süresi doldu, İade edildi. **Tek seferlik satın alma durumu değerleri**: Hiç satın alınmadı, Satın alındı, İade edildi. Alan türüne göre kullanılabilir operatörler: - **Metin (String)**: eşittir, eşit değil, ayarlanmış, ayarlanmamış. - **Sayı (Number)**: eşittir, eşit değil, küçüktür, büyüktür, küçük veya eşittir, büyük veya eşittir, arasında, ayarlanmış, ayarlanmamış. - **Tarih (Date)**: eşittir, eşit değil, önce, sonra, bu tarihte veya önce, bu tarihte veya sonra, arasında, ayarlanmış, ayarlanmamış. ## Tüm Kullanıcılar sistem segmenti \{#the-all-users-system-segment\} Adapty Mail, hiçbir filtresi olmayan yerleşik bir **All Users** segmentiyle birlikte gelir; projedeki her kullanıcı bu segmentin kapsamına girer. Bu segmenti düzenleyemez veya silemezsiniz. Bir flow içinde kullanıldığında, en altta her şeyi kapsayan satır olarak işlev görür (öncelik kuralı için bkz. [Flow'lar](mail-flows)). ## Yaşam Döngüsü \{#lifecycle\} Bir segmentin durumu, nasıl kullanıldığına göre hesaplanır: - **Draft**: Oluşturulmuş, herhangi bir flow veya A/B testine bağlı değil. - **Live**: Aktif bir flow veya A/B testine bağlı. - **Inactive**: Daha önce bağlıydı, ancak A/B testi sona erdi veya flow satırı kaldırıldı. - **Archived**: Geçici olarak silinmiş ve ana listeden gizlenmiş. Segments sayfasında, listeyi bu durumlardan herhangi birine göre daraltmak için araç çubuğunda bir durum filtresi bulunur. ## Segment düzenleme ve silme \{#edit-and-delete-a-segment\} - **Ad ve açıklama**: Her zaman düzenlenebilir. - **Taslak segment filtreleri**: Tamamen düzenlenebilir. - **Canlı segment filtreleri**: Kilitli. Bir segment aktif bir flow satırı veya A/B testi tarafından referans alındığında filtreler salt okunur hale gelir. Yalnızca adını veya açıklamasını güncelleyebilirsiniz. Hedeflemeyi değiştirmek için yeni bir segment oluşturun ve flow satırını değiştirin. - **Silme**: Segmenti geçici olarak siler. Canlı segmentler silinemez — önce flow'dan kaldırın (veya A/B testini tamamlayın). ## Sınırlamalar \{#limitations\} - **OR mantığı yok, iç içe geçme yok**: Filtreler yalnızca AND ile birleşir. - **Segment başına bir alan**: Bir segment, aynı alan üzerinde iki filtre içeremez (örneğin, iki ülke kontrolü). - **Boyut önizlemesi yok**: Düzenleyici, filtreleri şu anda kaç kullanıcının karşıladığını göstermez. - **Yayına alındıktan sonra filtreler kilitlenir**: Aktif segmentler, ad ve açıklama dışında salt okunurdur. --- # File: mail-profiles --- --- title: "Adapty Mail'de Profiller" description: "Projenizdeki her müşteriyi — özelliklerini, satın alma durumunu, e-posta etkileşimini ve tam aktivite geçmişini — görüntüleyin." --- **Profil**, projenizdeki tek bir müşteriyi temsil eder. **Profiles** sayfası, Adapty Mail'in tanıdığı herkesi listeler ve her kişinin satın alma sonucunu, e-posta etkileşimini ve tam aktivite geçmişini gösterir. Profiller otomatik olarak oluşur: Adapty SDK'nın topladığı e-postalardan ya da Adapty Mail API aracılığıyla gönderdiğiniz verilerden gelir. :::tip Flow'lar ve A/B testleri için profilleri yeniden kullanılabilir kitlelere gruplamak amacıyla [Segmentler](mail-segments) bölümüne bakın. ::: ## Profiller Adapty Mail'e nasıl eklenir \{#how-profiles-get-into-adapty-mail\} Adapty Mail, profilleri iki kaynaktan otomatik olarak oluşturur: - **Adapty SDK**: SDK, uygulamanızdan e-postaları ve satın alımları toplar. Bkz. [Kullanıcı e-postalarını toplama](mail-collect-emails). - **Adapty Mail API**: Backend'iniz profilleri ve işlemleri sunucudan sunucuya gönderir. Bkz. [API aracılığıyla veri gönderme](mail-send-data-via-api). Adapty Mail, her e-postayı, tıklamayı ve satın almayı kararlı `external_profile_id` aracılığıyla bir profile bağlar. Profiller sayfası salt okunurdur. Profilleri görüntüleyebilir ve aboneliklerini iptal edebilirsiniz, ancak oluşturma, düzenleme veya silme işlemi yapamazsınız. Bu verinin sahibi kaynak uygulama veya API'dir. ## Profil listesi \{#the-profiles-list\} Liste, her profil için bir satır gösterir; en yeniler en üstte yer alır. E-posta, profil ID'si veya harici profil ID'si ile profil aramak için arama kutusunu kullanın. | Sütun | Gösterilen | | --- | --- | | Profile | Müşterinin e-postası ve kendisine en fazla e-posta gönderen kampanya. | | Status | Profilin satın alma durumu. Bkz. [Profil durumu](#profile-status). | | Country | Müşterinin ülkesi. | | Open rate | Tüm e-postalar genelinde açılma sayısının gönderilme sayısına oranı. Tire işareti, henüz e-posta gönderilmediğini gösterir. | | LTV | Yaşam boyu değer — bu profilden tüm kaynaklarda elde edilen toplam gelir. | | Joined | Profilin Adapty Mail'e ilk girdiği tarih. | | Last activity | Profilin en son bir e-postayla etkileşime girdiği zaman; gönderim, açma veya tıklama gibi. | :::important **Joined** (Katılma Tarihi), profilin Adapty Mail'e ilk girdiği tarihtir ve "müşteri olma tarihi" olarak kullanılır. Bu tarih, uygulamanızdaki orijinal kayıt tarihi değil, sisteme eklenme zamanıdır. ::: ### Profil durumu \{#profile-status\} **Status** sütunu, profilin satın alma durumunu gösterir — yani müşterinin abonelikler ve tek seferlik satın almalar açısından mevcut konumunu. | Durum | Anlam | | --- | --- | | Never purchased | Profil henüz hiçbir şey satın almamış. | | Purchased | Profil bir tek seferlik satın alma gerçekleştirmiş. | | Active subscriber | Profilin aktif bir aboneliği var. | | Cancelling | Otomatik yenileme kapalı; erişim mevcut dönem sonuna kadar devam eder. | | Billing issue | Yenileme ödemesi başarısız oldu. | | Grace period | Ödeme başarısız oldu, ancak mağazanın ek süresi boyunca erişim devam eder. | | Churned | Abonelik süresi doldu ve erişim sona erdi. | | Refunded | Bir satın alma iade edildi. | :::note Satın alma durumu, e-posta abonelik durumundan ayrıdır. Bir profil **Aktif abone** olabilirken e-postalarınızdan **Abonelikten çıkmış** olabilir ya da **Churn** yaşamış olmasına rağmen hâlâ **Abone** olabilir. E-posta durumu profil sayfasında görünür ve Adapty Mail'in o profile e-posta gönderip gönderemeyeceğini belirler. ::: ## Profil detayları \{#profile-details\} Bir profile tıklayarak detay sayfasını açın. Başlık; e-posta, ülke, platform ve "müşteri olma tarihi" bilgilerini gösterir. Aynı zamanda üç durum rozeti de görüntülenir: satın alma durumu, açılma oranı ve profilin **Subscribed** (Abone) ya da **Unsubscribed** (Abonelikten Çıkmış) olup olmadığı. Sayfanın üst kısmında beş etkileşim metriği yer alır: - **Sent**: Profile gönderilen e-postalar. - **Delivered**: Posta kutusu sağlayıcısının kabul ettiği e-postalar. - **Opened**: Profilin açtığı e-postalar. - **Clicked**: Profilin bir bağlantıya tıkladığı e-postalar. - **Revenue**: İki değer — attributed gelir ve yaşam boyu değer. :::note **Attributed revenue** (ilişkilendirilen gelir), e-postalarınızın sağladığı geliri ifade eder: profilin bir kampanyayla etkileşime girdikten sonra yaptığı satın almalar. **Yaşam boyu değer (LTV)** ise e-postanın katkısı olup olmadığından bağımsız olarak profilin tüm kaynaklardan elde edilen toplam geliridir. Başlık, önce ilişkilendirilen geliri, ardından LTV'yi gösterir. ::: **Profile** kartı, müşterinin özelliklerini listeler: - **Platform**: Müşterinin cihaz platformu; iOS veya Android gibi. - **Country**: Müşterinin ülkesi. - **Store country**: Müşterinin App Store veya Google Play hesabının ülkesi. - **Gender**: Müşterinin cinsiyeti (biliniyorsa). - **Age**: Müşterinin yaşı (doğum günü girildiyse). - **Profile ID**: Adapty Mail'in profil için kullandığı dahili tanımlayıcı. - **External ID**: Uygulamanızdan veya backend'inizden gelen `external_profile_id`. - **Custom attributes**: Profille birlikte gönderdiğiniz tüm anahtar-değer çiftleri. ### Satın alma durumu \{#purchase-state\} **Purchase state** kartı, profilin gelirini ve satın alma geçmişini gösterir. Lifetime value en üstte yer alır; ardından en fazla iki bölüm gelir: - **Subscription**: Profilin aboneliği için fiyat, mağaza, başlangıç tarihi, yenileme veya bitiş tarihi ve ürün kimliği. - **One-time purchase**: En son tek seferlik satın alma için fiyat, mağaza, satın alma tarihi ve ürün kimliği. Profil henüz hiçbir şey satın almamışsa kart **No purchase yet** olarak gösterilir. **Segments** kartı, profilin şu anda eşleştiği tüm segmentleri listeler; hiçbiri geçerli değilse **Not in any segment** gösterir. Üyelik anlık olarak değerlendirildiğinden her zaman en güncel profil verilerini yansıtır. Segmentlerin nasıl oluşturulacağını öğrenmek için [Segments](mail-segments) bölümüne bakın. ## Aktivite yolculuğu \{#the-activity-journey\} **Journey** bölümü, profilde gerçekleşen her şeyin zaman çizelgesidir. **Profile created** ile başlar ve ardından iki tür etkinliği iç içe gösterir: - **E-posta etkinlikleri**: Profile gönderilen her e-posta; teslimat, açılma ve tıklama aktivitesiyle birlikte. Bir e-postayı genişleterek profilin tıkladığı bağlantıları ve e-postanın sağladığı satın alımı görebilirsiniz. - **İşlem etkinlikleri**: Başlangıçlar, yenilemeler, iptaller, ödeme sorunları, süre bitişleri ve iade gibi abonelik ve tek seferlik satın alma dönüm noktaları. İşlem etkinlikleri şu yolculuk etiketleriyle eşleşir: | `event_type` | Journey etiketi | | --- | --- | | `subscription_started` | Abonelik başladı | | `subscription_renewed` | Abonelik yenilendi | | `subscription_renewal_cancelled` | Yenileme iptal edildi | | `subscription_renewal_reactivated` | Yenileme devam ettirildi | | `billing_issue_detected` | Fatura sorunu | | `entered_grace_period` | Ek süreye girildi | | `subscription_expired` | Abonelik sona erdi | | `subscription_refunded` | Abonelik iade edildi | | `non_subscription_purchase` | Tek seferlik satın alma | | `non_subscription_purchase_refunded` | Satın alma iade edildi | Bu olaylar Adapty SDK aracılığıyla otomatik olarak Adapty Mail'e ulaşır ya da API üzerinden kendiniz gönderebilirsiniz. Olay referansı için bkz. [İşlem olaylarını gönder](mail-send-data-via-api#send-transaction-events). ## Bir profili abonelikten çıkarma \{#unsubscribe-a-profile\} Bir profile e-posta göndermeyi durdurmak için profilin sayfasını açın, **...** simgesine tıklayın ve **Unsubscribe** seçeneğini belirleyin. Adapty Mail, profili abonelikten çıkarılmış olarak işaretler ve baskı listesine ekler; böylece kampanyalar ve flow'lar bu profili atlar. Bu işlem idempotenttir: zaten abonelikten çıkarılmış bir profil abonelikten çıkarılmış olmaya devam eder. Baskı ve profillerin kendi kendine abonelikten çıkması hakkında kapsamlı bilgi için bkz. [Abonelikten çıkma ve baskı](mail-suppression). --- # File: mail-ab-testing --- --- title: "Adapty Mail'de A/B testi" description: "Bir flow'a A/B testi ekleyerek tam e-posta kampanyalarını birbirleriyle karşılaştırın." --- Adapty Mail'deki bir A/B testi, iki veya daha fazla tam e-posta kampanyasını birbiriyle karşılaştırır. Her varyant, bağımsız ve eksiksiz bir kampanyadır. Bir kullanıcı [flow](mail-flows) içindeki testin segmentiyle eşleştiğinde, Adapty Mail kullanıcıyı yapılandırılmış ağırlıkları kullanarak varyantlardan birine yönlendirir ve her varyant için teslim, etkileşim ve geliri takip eder. ## Varyant nedir \{#what-a-variation-is\} Her varyant tam bir kampanyadır. Varyantlar, bir kampanyanın farklılaşabileceği her şeyde farklı olabilir — metin, ana görseller, ton, dizi uzunluğu veya e-postalar arasındaki gecikme süresi. A/B testinin kendisi bunları ayrı ayarlar olarak sunmaz; kampanyaları ayrı ayrı oluşturup varyant olarak eklersiniz. ## A/B testi oluşturma \{#create-an-ab-test\} 1. Önce **Campaigns** bölümünde kampanyaları oluşturun. Her varyantın kendi kampanyasına ihtiyacı vardır. 2. Adapty Mail'de **A/B Tests** bölümüne gidin ve **Create**'e tıklayın. 3. Her kampanyayı varyant olarak ekleyin ve ağırlığını ayarlayın. Ağırlıkların toplamı **%100** olmalıdır. 4. Testin hangi kullanıcılara uygulanacağını belirlemek için bir segment atayın. 5. Kaydedin. Test **taslak** olarak kaydedilir ve henüz herhangi bir şey göndermez. Yayına almak için bir flow'a eklenmesi gerekir. ## Flow'dan başlatma \{#launch-from-a-flow\} A/B testleri A/B Tests sayfasından başlatılamaz — hem başlatma hem de bitirme işlemleri bir flow satırı içinde gerçekleşir. 1. Adapty Mail'de **Flows** bölümüne gidin ve testi çalıştırmak istediğiniz tetikleyiciyi açın. 2. Yeni bir satırda **Create**'e tıklayın. İletişim kutusunda **Content type** alanını **A/B Test** olarak ayarlayın, kaydettiğiniz testi seçin ve **Save**'e tıklayın. 3. Satırda **Launch A/B test**'e tıklayın. Testin durumu **taslak**tan **yayında**ya geçer ve segmentle eşleşen gelen kullanıcılar varyantlara yönlendirilmeye başlar. Flow satırları hakkında daha fazla bilgi için [Flow oluşturma](mail-create-flow) bölümüne bakın. ## Yönlendirme nasıl çalışır \{#how-routing-works\} Bir kullanıcı flow'un tetikleyicisine ulaştığında ve A/B testinin segmentiyle eşleştiğinde, Adapty Mail **ağırlıklı rastgele** seçim kullanarak bir varyant belirler — her varyantın ağırlığı, çekilişteki payını belirler. Yönlendirme, kullanıcı başına deterministik değildir. ## Sonuçları okuma \{#read-results\} A/B Tests sayfasında her varyant, ham sayaçlarını ve türetilmiş oranlarını gösterir: - **Delivery**: Gönderilenler, Teslim Edilenler, Geri Dönenler. - **Engagement**: Açılmalar, Tıklamalar, Abonelik İptalleri. - **Revenue**: Satın Almalar, Gelir. Her metriğin neyi saydığı ve gelirin nasıl atfedildiği hakkında bilgi için [Kampanya analitiği](mail-analytics) bölümüne bakın. ## Testi bitirme \{#finish-the-test\} Başlatmada olduğu gibi, bitirme işlemi de A/B Tests sayfasından değil, flow satırından gerçekleşir. 1. Testin çalıştığı flow satırını açın. 2. **Finish A/B test**'e tıklayın. 3. **Finish A/B test** iletişim kutusunda **Replace with campaign** açılır menüsünden kazanan kampanyayı seçin — veya segmenti flow'dan tamamen kaldırmak için boş bırakın. 4. Onaylayın. :::note Herhangi bir varyantın — kazanan veya kaybeden — ortasında olan kullanıcılar, planlanmış e-postalarını almaya devam eder. Kazanana geçirilmezler. ::: ## Yaşam döngüsü \{#lifecycle\} Bir A/B testi dört durumdan geçer: - **Draft**: Oluşturulmuş, henüz yayındaki bir flow satırına eklenmemiş. - **Live**: Eklenmiş ve başlatılmış; gelen kullanıcıları yönlendiriyor. - **Finished**: **Finish A/B test** ile durdurulmuş. - **Archived**: Listeden geçici olarak silinmiş. --- # File: mail-analytics --- --- title: "Adapty Mail'de Analitik" description: "Kampanya performansını kampanya, segment, A/B varyantı, mesaj veya tetikleyiciye göre dilimleyin; teslimat, etkileşim ve geliri yan yana görün." --- **Analytics** sayfası, kampanyalarınızın performansını beş boyutta gösterir: kampanya, segment, A/B varyantı, mesaj ve tetikleyici. Teslimat metrikleri ile her e-postaya atfedilen geliri bir arada sunarak varyantları karşılaştırmanıza, en iyi performans gösteren segmentleri bulmanıza ve gelirin nerede yoğunlaştığını görmenize olanak tanır. Sayfanın üst kısmında bir grafik, alt kısmında ise bir dökümü tablosu yer alır. Tek bir varlığın ayrıntılarına inmek için herhangi bir satıra tıklayın. ## Zaman aralığı seçin \{#pick-a-time-range\} Sayfanın üstündeki araç çubuğu, zaman penceresini ve verilerin nasıl gruplandırılacağını kontrol eder: - **Tarih aralığı**: Hazır seçenekler (Son 7 / 14 / 30 / 90 gün, Bu ay, Geçen ay, Son 12 ay, Yılbaşından bugüne) veya **Özel aralık** seçici. Varsayılan değer son 30 gündür. - **Granülarite**: **Günlük**, **Haftalık** veya **Aylık** gruplar. Aralık büyüdükçe granülarite otomatik olarak kalaşır — 92 günü geçince **Günlük** yerine **Haftalık**, 366 günü geçince her ikisi de **Aylık**'a geçer. - **Grafik stili**: **Çizgi**, **Alan** veya **Çubuk**. Sayfa "range too wide" uyarısı gösteriyorsa, tarih aralığını daraltın, granülerliği kaba hale getirin veya filtre uygulayın. ## Grupla, parçala, filtrele \{#group-break-down-filter\} Araç çubuğunun altındaki üç kontrol, grafik ve tablonun ne göstereceğini belirler: - **Group by**: Veri setini satırlara bölen boyut. Seçenekler: **Campaigns**, **Segments**, **A/B variants** ve **Triggers**. **No grouping** seçildiğinde sayfa her şeyi tek bir toplu **All** satırında gösterir. - **Breakdown**: Her satırı alt satırlara bölen ikinci boyut. Hem **Group by** hem de **Breakdown** ayarlandığında, tablodaki her satır alt gruplarını görmek için genişletilebilir. Breakdown, **Messages** dahil olmak üzere **Group by** için kullanılan boyut dışındaki herhangi bir boyut olabilir. - **Add filter**: Veri setini belirli kampanyalar, segmentler, A/B varyantları veya tetikleyicilerle sınırlandırır. Filtreler hem grafiğe hem de tabloya uygulanır. :::note **Messages**, üst düzey bir **Group by** veya filtre olarak değil, yalnızca bir breakdown olarak kullanılabilir. Bireysel mesajları analiz etmek için **Messages** breakdown'ıyla birlikte **Campaigns** grubuna göre gruplandırın, ardından kampanya satırını genişletin ya da drilldown üzerinden bir mesaj açın. ::: ## Grafiği okuma \{#read-the-chart\} Grafik, seçilen zaman aralığında belirlediğiniz metrikleri görüntüler. - **Metrik kategorisi**: **Email actions** (Sent, Delivered, Opened, Clicked, Bounced, Unsubscribed, Converted) ile **Revenue** arasında geçiş yapın. - **Metrik pilleri**: Hangi metriklerin çizileceğini seçin. Toplu modda (gruplama yok), aynı grafikte birden fazla metrik çizebilirsiniz. Gruplama açıkken grafik tek bir metrik çizer; her grup için ayrı bir çizgi oluşturulur, böylece gruplar görsel olarak birbirinden ayrışır. - **Gösterge**: Gruplama açıkken sağdaki gösterge tüm grupları listeler ve her bir serisi açıp kapatmanıza olanak tanır. Aşağıdaki metrikler tablosundaki görünürlük onay kutuları, grafikte hangi satırların görüneceğini de kontrol eder. ## Metrikler tablosunu okuyun \{#read-the-metrics-table\} Grafiğin altındaki metrikler tablosu, her grup için bir satır listeler. En üstteki özet satırı, tablodaki diğer tüm satırları bir araya getirir. - **Sıralanabilir sütunlar**: Herhangi bir sütun başlığına tıklayarak Name, Sent, Delivered, Delivery rate, Opened, Open rate, Clicked, Click rate, Converted, Revenue, Bounced veya Unsubscribed sütunlarına göre sıralama yapabilirsiniz. - **Görünürlük onay kutusu**: Bir satırın grafikte görünüp görünmeyeceğini açıp kapatır. - **Satırı genişlet**: Bir **Breakdown** ayarlandığında, her satırın solundaki şevronu tıklayarak alt gruplara açabilirsiniz. - **Detay görünümünü aç**: Bir satırın adına tıklayarak o varlığa ait odaklanmış görünümü açabilirsiniz. Ayrıntı görünümünde şunlar yer alır: - Ana sayfayla aynı grafik ve metrik seçici; tek bir varlığa göre kapsamlandırılmış. - Altta sekiz özet kart: **Sent**, **Delivered** (teslim oranıyla birlikte), **Opened** (açılma oranıyla birlikte), **Clicked** (tıklanma oranıyla birlikte), **Bounced**, **Unsubscribed**, **Converted** ve **Revenue**. Tarih aralığı ve ayrıntı düzeyi ana sayfadan aktarılır. Geri dönmek için içerik izinde yer alan **Back** düğmesini kullanın. ## Neler izlenir \{#whats-tracked\} :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: Her satır — Analytics sayfasında, detay görünümünde ve aşağıda açıklanan satır içi görünümlerde — aynı ham sayım kümesini gösterir: - **Sent**: SES'e iletilen e-postalar. - **Delivered**: SES tarafından onaylanan gelen kutusu teslimatları. - **Bounced**: SES tarafından bildirilen geri dönüşler. Kalıcı ve geçici geri dönüşler ayrıştırılmaz; her ikisi de tek bir **Bounced** olarak sayılır. - **Opened**: Piksel yüklemeleri. Apple Mail Gizlilik Koruması, iOS 15 ve sonrasında görselleri önceden getirdiğinden bu sayı şişebilir — daha güvenilir sinyaller için tıklama ve gelir verilerini kullanın. - **Clicked**: E-posta gövdesindeki bağlantı tıklamaları. - **Unsubscribed**: Alt bilgi bağlantısından veya `List-Unsubscribe` başlığından gerçekleştirilen abonelik iptalleri. - **Converted**: Zaman aralığında attribution edilmiş satın alması bulunan gruptaki benzersiz profiller. Dönüşümler satın alma tarihine göre gruplandırılır; Mart'ta gerçekleşen bir tıklama ve Nisan'daki bir satın alma, Nisan'a dahil edilir. Birden fazla satın alma yapan bir profil yine de bir kez sayılır. - **Revenue**: Abonelik başlangıçları, yenilemeler ve tek seferlik satın almalar genelinde attribution edilmiş gelirin (USD) toplamı. ## Türetilmiş oranlar \{#derived-rates\} Her oran, yukarıdaki ham sayımlardan hesaplanır: | Oran | Formül | | ------------- | -------------------- | | Teslimat oranı | Teslim edilen / Gönderilen | | Açılış oranı | Açılan / Teslim edilen | | Tıklama oranı | Tıklanan / Teslim edilen | Detay görünümü, özet kartlarının yanında aynı üç oranı gösterir. ## Gelir attribution'ı \{#revenue-attribution\} Gelir, takip edilen bir bağlantı üzerindeki **son tıklama** ile ilişkilendirilir: 1. Bir alıcı e-postadaki herhangi bir bağlantıya tıkladığında, Adapty Mail ilgili profilin `scheduled_email_id` değerini kısa süreli bir depoda saklar. 2. Ardından gelen bir satın alma olayında mevcut bir attribution yoksa, Adapty Mail saklanan `scheduled_email_id` değerini işleme geri yükler — satın alma zaman damgasının tıklamadan sonra olması koşuluyla. 3. Öncesinde takip edilen bir tıklama bulunmayan satın almalar attribution'sız kalır. İzlenen parametre `scheduled_email_id`'dir. Ödeme URL'si ayrıca `{email}` ve `{external_profile_id}` yer tutucuları aracılığıyla alıcının kimliğini taşır; böylece web paywall'u akışı kişiselleştirebilir — bu, attribution'dan ayrı bir mekanizmadır. Bkz. [Ödeme kurulumu](mail-checkout). ## Flow'larda ve A/B Testlerinde Satır İçi Analizler \{#inline-analytics-in-flows-and-ab-tests\} Aynı metrikler, ölçülen satırların hemen yanında da görünür: - **Flow'lar sayfası**: Bir tetikleyici görünümündeki her segment satırı, teslimat, etkileşim ve gelir sayılarını gösterir. - **A/B Testleri sayfası**: Varyantlar, aynı metrik setiyle yan yana listelenir; bu da varyantları doğrudan karşılaştırmayı kolaylaştırır. Kampanyalar arasında karşılaştırma yaparken veya tek bir öğeyi derinlemesine incelemek istediğinizde Analytics sayfasını, belirli bir akış satırı veya A/B testi üzerinde çalışırken ise satır içi görünümleri kullanın. Yukarıda açıklanan metrik tanımları, türetilmiş oranlar ve attribution kuralları her üç görünüm için de aynı şekilde geçerlidir. ## Sınırlamalar \{#limitations\} - **Soft ve hard bounce ayrımı yok**: Geçici ya da kalıcı her bounce, tek bir **Bounced** sayısına dahil edilir. - **Anlık değil, nihai tutarlılık**: Sayılar, olay tablolarından toplanır. Yeni olaylar genellikle birkaç dakika içinde görünür, ancak gerçek zamanlı akış garantisi yoktur. - **Tarih aralığı boyutu sınırlıdır**: Çok geniş tarih aralıkları, ince granülerlikle birleştirildiğinde grafiğin hücre sınırını aşabilir. Bu durumda sayfa "aralık çok geniş" uyarısı gösterir — aralığı daraltın, granülerliği kaba ayarlayın ya da filtre uygulayın. --- # File: configuration --- --- title: "Üçüncü taraf entegrasyonu yapılandırma" description: "Abonelik yönetimini optimize etmek için Adapty ayarlarını nasıl yapılandıracağınızı öğrenin." --- Adapty entegrasyonları sayesinde abonelik etkinliklerini ve satın alma verilerini tercih ettiğiniz platforma veya iş akışına sorunsuzca iletebilirsiniz. Kullanıcı davranışı içgörüleri, müşteri etkileşim stratejileri veya pazarlama ekibiniz için gelişmiş ürün analitiği arıyor olsanız da Adapty, uygulama içi satın alma etkinliklerini seçtiğiniz entegrasyona zahmetsizce iletir. Adapty; denemeler, dönüşümler, yenilemeler ve iptaller gibi uygulama içi satın alma ve abonelik etkinliklerini otomatik olarak takip eder. Bu [etkinlikler](events), seçtiğiniz entegrasyonlara otomatik olarak iletilir. Bu sayede müşterilerle mevcut aşamalarına göre etkileşime geçebilir ve uygulamanızdaki gelirle ilgili faaliyetleri analiz edebilirsiniz. ## Entegrasyon ayarları \{#integration-settings\} <img src="/assets/shared/img/20bf659-CleanShot_2023-08-22_at_13.26.562x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Entegrasyonlar, bu entegrasyon üzerinden gönderilen tüm etkinlikleri etkileyen şu yapılandırma seçeneklerini sunar: | Ayar | Açıklama | |:--------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Reporting Proceeds** | Gelir değerlerinin nasıl gösterileceğini seçin: App Store ve Play Store komisyonları düşüldükten sonra net olarak mı, yoksa kesintilerden önce brüt olarak mı. "Send sales as proceeds" onay kutusunu işaretleyerek satışları App Store / Play Store komisyonları düşüldükten sonraki net tutar olarak görüntüleyebilirsiniz. | | **Send Trial Price** | İşaretlenirse Adapty, Trial Started etkinliği için abonelik fiyatını iletir. | | **Exclude Historical Events** | Kullanıcının Adapty SDK'lı uygulamayı yüklemesinden önce gerçekleşen etkinlikleri hariç tutmayı seçin. Bu, etkinliklerin tekrarlanmasını önler ve doğru raporlama sağlar. Örneğin, bir kullanıcı 10 Ocak'ta aylık abonelik başlattıysa ve uygulamayı 6 Mart'ta Adapty SDK ile güncellediyse, Adapty 6 Mart öncesindeki etkinlikleri atlayıp sonrakileri aktarır. | | **Report User's Currency** | Satışların kullanıcının para biriminde mi yoksa USD cinsinden mi raporlanacağını seçin. | | **Send User Attributes** | Dil tercihleri gibi kullanıcıya özgü nitelikleri göndermek istiyorsanız ve OneSignal planınız 10'dan fazla etiketi destekliyorsa bu seçeneği işaretleyin. Bu seçeneği etkinleştirmek, varsayılan 10 etiketin ötesinde ek bilgilerin dahil edilmesine olanak tanır. Etiket sınırlarının aşılması hatalara yol açabilir. | | **Send Attributions** | Attribution bilgilerini (ör. AppsFlyer attribution) iletmek ve ilgili ayrıntıları almak için bu seçeneği etkinleştirin. | | **Send Play Store purchase token** | Gerektiğinde satın almayı yeniden doğrulamak için gereken Play Store token'ını almak üzere bu seçeneği etkinleştirin. Etkinleştirildiğinde etkinliğe `play_store_purchase_token` parametresi eklenir. | | **Delay events with future datetime** | **Yalnızca AppsFlyer ve özel webhook'lar için**: Etkinleştirildiğinde, yenileme ve deneme dönüşüm etkinlikleri gerçekleştikleri tarihte gönderilir. Devre dışı bırakıldığında (varsayılan), bu etkinlikler tarih gelecekte olsa bile algılandığı anda gönderilir. | | **Data residency** | **Yalnızca Mixpanel ve Amplitude için**: Etkinliklerinizin nerede işlenip depolanacağını belirlemek üzere veri yerleşimini seçin. | ## Etkinlikleri yapılandırma \{#configure-the-events\} Kimlik bilgilerinin altında, Adapty'den seçili entegrasyon platformuna gönderebileceğiniz üç etkinlik grubu bulunur. İhtiyaç duyduklarınızı etkinleştirmeniz gerekir. Etkinlik adı özelleştirmesinin yalnızca belirli entegrasyonlarda mevcut olduğunu, diğerlerinde ise etkinlik adlarının sabit olduğunu ve değiştirilemediğini belirtmek gerekir. Ayrıca [Airbridge](airbridge#configure-events-and-tags) gibi bazı entegrasyonlarda tek bir Adapty etkinliğine birden fazla etkinlik adı atama esnekliğine sahipsiniz. Adapty tarafından sunulan etkinliklerin tam listesini [buradan](events) inceleyebilirsiniz. <img src="/assets/shared/img/c79f5cd-screencapture-app-adapty-io-integrations-pushwoosh-2023-08-22-13_31_07.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin varsayılan etkinlik adlarını kullanmanızı öneririz; ancak etkinlik adlarını özel gereksinimlerinize göre uyarlama özgürlüğüne de sahipsiniz. --- # File: events --- --- title: "Üçüncü taraf entegrasyonlara gönderilecek olaylar" description: "Adapty'nin analitik araçlarını kullanarak önemli abonelik olaylarını takip edin." --- Apple ve Google, abonelik olaylarını [App Store Sunucu Bildirimleri](enable-app-store-server-notifications) ve [Gerçek Zamanlı Geliştirici Bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) aracılığıyla doğrudan sunuculara gönderir. Bu nedenle mobil uygulamalar, olayları analitik sistemlere gerçek zamanlı olarak güvenilir biçimde iletamaz. Örneğin bir kullanıcı abone olup uygulamayı bir daha açmazsa, geliştirici sunucu olmadan hiçbir abonelik durum güncellemesi alamaz. Adapty bu boşluğu, abonelik verilerini toplayıp okunabilir olaylara dönüştürerek kapatır. Bu entegrasyon olayları JSON formatında gönderilir. Tüm olaylar aynı yapıyı paylaşsa da alanları olay türüne, mağazaya ve belirli yapılandırmaya göre farklılık gösterir. Her olaya dahil edilen tam alanları ilgili entegrasyon sayfalarında bulabilirsiniz. Bir olayın başarıyla işlenip işlenmediğini veya bir sorun olup olmadığını nasıl anlayacağınızı öğrenmek için [Olay durumları](event-statuses) sayfasına göz atın. ## Olay türleri \{#event-types\} Olayların büyük çoğunluğu oluşturulup etkinleştirildiklerinde yapılandırılmış tüm entegrasyonlara gönderilir. Ancak **Access level updated** olayı yalnızca [webhook entegrasyonu](webhook) yapılandırılmışsa ve bu olay etkinleştirilmişse tetiklenir. Bu olay [Event Feed](https://app.adapty.io/event-feed)'de görünecek ve webhook'a gönderilecektir; ancak diğer entegrasyonlarla paylaşılmaz. Bir webhook entegrasyonu yapılandırılmamışsa veya bu olay türü etkinleştirilmemişse **Access level updated** olayı oluşturulmaz ve [Event Feed](https://app.adapty.io/event-feed)'de görünmez. | Event name | Description | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | subscription_started | Kullanıcı deneme süresi olmaksızın ücretli bir abonelik etkinleştirdiğinde, yani anında ücretlendirildiğinde tetiklenir. | | subscription_renewed | Abonelik yenilendiğinde ve kullanıcı ücretlendirildiğinde gerçekleşir. Bu olay, deneme süreli veya deneme süresiz aboneliklerde ikinci ödemeden itibaren başlar. | | subscription_renewal_cancelled | Kullanıcı abonelik otomatik yenilemesini kapattığında tetiklenir. Kullanıcı, ücretli abonelik süresi sonuna kadar premium özelliklere erişmeye devam eder. | | subscription_renewal_reactivated | Kullanıcı abonelik otomatik yenilemesini yeniden etkinleştirdiğinde tetiklenir. | | subscription_expired | İptal edilen bir abonelik tamamen sona erdiğinde tetiklenir. Örneğin, kullanıcı aboneliğini 12 Aralık'ta iptal etmiş ancak abonelik 31 Aralık'a kadar aktif kalmaya devam ediyorsa, olay aboneliğin sona erdiği 31 Aralık'ta kaydedilir. | | subscription_paused | Kullanıcı [abonelik duraklatma](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause) özelliğini etkinleştirdiğinde gerçekleşir (yalnızca Android). | | subscription_deferred | Abonelik satın alımı [ertelendiğinde](https://adapty.io/glossary/subscription-purchase-deferral/) tetiklenir; kullanıcılar premium özelliklere erişimlerini sürdürürken ödemeyi geciktirebilir. Bu özellik Google Play Developer API aracılığıyla kullanılabilir ve ücretsiz denemeler için ya da mali güçlük yaşayan kullanıcılara destek sağlamak amacıyla kullanılabilir. | | non_subscription_purchase | Süresiz erişim veya oyun içi coin gibi consumable ürünler dahil, abonelik dışındaki tüm satın almalar. | | trial_started | Kullanıcı deneme aboneliği etkinleştirdiğinde tetiklenir. | | trial_converted | Deneme süresi sona erdiğinde ve kullanıcı ücretlendirildiğinde (ilk satın alma) gerçekleşir. Örneğin, kullanıcının denemesi 14 Ocak'a kadar sürüyor ancak 7 Ocak'ta ücretlendiriliyorsa, bu olay 7 Ocak'ta kaydedilir. | | trial_renewal_cancelled | Kullanıcı deneme süresi boyunca abonelik otomatik yenilemesini kapattığında tetiklenir. Kullanıcı deneme süresi sonuna kadar premium özelliklere erişmeye devam eder; ancak ücretlendirilmez ve abonelik başlatılmaz. | | trial_renewal_reactivated | Kullanıcı deneme süresi boyunca abonelik otomatik yenilemesini yeniden etkinleştirdiğinde gerçekleşir. | | trial_expired | Deneme süresi aboneliğe dönüşmeden sona erdiğinde tetiklenir. | | entered_grace_period | Ödeme girişimi başarısız olduğunda ve kullanıcı ek süreye girdiğinde gerçekleşir (etkinleştirilmişse). Kullanıcı bu süre boyunca premium erişimini korur. | | billing_issue_detected | Ücretlendirme girişimi sırasında bir ödeme sorunu oluştuğunda (örn. yetersiz kart bakiyesi) tetiklenir. | | subscription_refunded | Bir abonelik iade edildiğinde (örn. Apple Support tarafından) tetiklenir. | | non_subscription_purchase_refunded | Abonelik dışı bir satın alma iade edildiğinde tetiklenir. | | access_level_updated | Kullanıcının access level'ı güncellendiğinde gerçekleşir. | Yukarıdaki olaylar, kullanıcıların satın alma açısından durumunu eksiksiz biçimde kapsar. Birkaç örneğe bakalım. ### Örnek 1 \{#example-1\} _Kullanıcı 1 Nisan'da 7 günlük deneme süresiyle aylık bir abonelik başlattı. 4. günde aboneliğini iptal etti._ Bu durumda şu olaylar gönderilir: 1. 1 Nisan'da `trial_started` 2. 4 Nisan'da `trial_renewal_cancelled` 3. 7 Nisan'da `trial_expired` ### Örnek 2 \{#example-2\} _Kullanıcı 1 Nisan'da 7 günlük deneme süresiyle aylık bir abonelik başlattı. 10. günde aboneliğini iptal etti._ Bu durumda şu olaylar gönderilir: 1. 1 Nisan'da `trial_started` 2. 7 Nisan'da `trial_converted` 3. 10 Nisan'da `subscription_renewal_cancelled` 4. 1 Mayıs'ta `subscription_expired` Her senaryoda hangi olayların tetiklendiğine dair ayrıntılı bir döküm için [Olay akışları](event-flows) sayfasına bakın. --- # File: event-flows --- --- title: "Etkinlik akışları" description: "Adapty'deki abonelik etkinlik akışlarının ayrıntılı şemalarını keşfedin. Abonelik etkinliklerinin nasıl oluşturulduğunu ve integrasyonlara nasıl gönderildiğini öğrenerek müşterilerinizin yolculuklarındaki önemli anları takip edin." --- Adapty'de, bir müşterinin uygulamanızdaki yolculuğu boyunca çeşitli abonelik olayları alırsınız. Bu abonelik akışları, kullanıcılar abone olurken, iptal ederken veya aboneliklerini yeniden etkinleştirirken Adapty'nin ürettiği olayları anlamanıza yardımcı olmak için yaygın senaryoları özetler. Apple'ın abonelik ödemelerini gerçek başlangıç/yenileme zamanından birkaç saat önce işlediğini unutmayın. Aşağıdaki akışlarda, diyagramları sade tutmak amacıyla abonelik başlangıcı/yenilemesi ile ödemenin aynı anda gerçekleştiğini gösteriyoruz. Ayrıca, aynı işleme ilişkin olaylar eş zamanlı gerçekleşir ve **Event Feed** bölümünüzde diyagramlarımızda gösterilen sıradan farklı bir sırayla görünebilir. ## Abonelik Yaşam Döngüsü \{#subscription-lifecycle\} ### İlk Satın Alma Akışı \{#initial-purchase-flow\} Bu akış, bir müşteri deneme süresi olmadan ilk kez abonelik satın aldığında gerçekleşir. Bu durumda aşağıdaki olaylar oluşturulur: - **Subscription started** - **Access level updated**: kullanıcıya erişim izni vermek için Abonelik yenileme tarihi geldiğinde abonelik yenilenir. Bu durumda aşağıdaki olaylar oluşturulur: - **Subscription renewal**: aboneliğin yeni bir dönemini başlatmak için - **Access level updated**: aboneliğin son kullanma tarihini güncelleyerek erişimi bir dönem daha uzatmak için Ödemenin başarısız olduğu veya kullanıcının yenilemeyi iptal ettiği durumlar sırasıyla [Billing Issue Outcome Flow](event-flows#billing-issue-outcome-flow) ve [Subscription Cancellation Flow](event-flows#subscription-cancellation-flow) bölümlerinde açıklanmaktadır. <img src="/assets/shared/img_webhook_flows/Initial_Purchase_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Abonelik İptal Akışı \{#subscription-cancellation-flow\} Bir kullanıcı aboneliğini iptal ettiğinde aşağıdaki olaylar oluşturulur: - **Subscription renewal canceled**: Aboneliğin mevcut dönemin sonuna kadar aktif kaldığını, ardından kullanıcının erişimini kaybedeceğini belirtir. - **Access level updated**: Access level için otomatik yenilemeyi devre dışı bırakmak amacıyla oluşturulur. Abonelik sona erdiğinde, aboneliğin bitişini işaretlemek için **Subscription expired (churned)** olayı tetiklenir. <img src="/assets/shared/img_webhook_flows/Subscription_Cancellation_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bir iade onaylanırsa, **Subscription expired (churned)** yerine şu olay gelir: - **Subscription refunded**: aboneliği sona erdirir ve iade hakkında ayrıntı sağlar <img src="/assets/shared/img_webhook_flows/Subscription_Cancellation_Flow_with_a_Refund.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Stripe'ta bir abonelik, kalan süre atlanarak anında iptal edilebilir. Bu durumda tüm olaylar aynı anda oluşturulur: - **Subscription renewal cancelled** - **Subscription expired (churned)** - **Access Level updated** (kullanıcının erişimi kaldırılır) Bir iade onaylanırsa, onaylandığında aynı zamanda bir **Subscription refunded** olayı da tetiklenir. <img src="/assets/shared/img_webhook_flows/Subscription_Immediate_Cancellation_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Abonelik Yeniden Etkinleştirme Akışı \{#subscription-reactivation-flow\} Bir kullanıcı aboneliğini iptal ederse, abonelik sona erer ve kullanıcı daha sonra aynı aboneliği yeniden satın alırsa, bir **Subscription renewed** olayı oluşturulur. Erişimde bir kesinti olsa bile Adapty, bunu `vendor_original_transaction_id` ile bağlantılı tek bir işlem zinciri olarak değerlendirir. Dolayısıyla yeniden satın alma, bir yenileme olarak kabul edilir. **Access level updated** olayları iki kez oluşturulur: - abonelik sona erdiğinde kullanıcının erişimini iptal etmek için - abonelik yeniden satın alındığında erişim vermek için <img src="/assets/shared/img_webhook_flows/Subscription_Rejoin_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Abonelik Duraklatma Akışı (Yalnızca Android) \{#subscription-pause-flow-android-only\} Bu akış, bir kullanıcının Android'de aboneliğini duraklatıp daha sonra devam ettirmesi durumunda geçerlidir. Aboneliği duraklatmanın etkileri hemen gerçekleşmez. Kullanıcı bir aboneliği yenilenmeden önce duraklatırsa, abonelik aktif kalmaya devam eder ve kullanıcı mevcut fatura döneminin sonuna kadar ücretli erişimini korur. 1. Kullanıcı bir aboneliği duraklatığında **Subscription paused (Android only)** etkinliği tetiklenir. 2. Abonelik döneminin sonunda Adapty, kullanıcının erişimini iptal etmek için **Access level updated** etkinliğini tetikler. 3. Kullanıcı aboneliği yeniden başlattığında şu etkinlikler tetiklenir: - **Subscription renewed** - Kullanıcının erişimini geri yüklemek için **Access level updated** Bu abonelikler, aynı **vendor_original_transaction_id** ile bağlantılı olarak aynı işlem zincirinde yer alır. <img src="/assets/shared/img_webhook_flows/Subscription_Paused_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Trial Akışları \{#trial-flows\} Uygulamanızda deneme süresi kullanıyorsanız, deneme süresine ilişkin ek etkinlikler alırsınız. ### Başarılı Dönüşümlü Deneme Akışı \{#trial-with-successful-conversion-flow\} En yaygın akış, kullanıcının bir deneme başlatması, kredi kartı bilgilerini girmesi ve deneme süresi sonunda standart aboneliğe başarıyla geçmesiyle gerçekleşir. Bu durumda, deneme başlangıcı anında şu olaylar oluşturulur: - **Trial started** — denemenin başladığını işaretler - **Access level updated** — erişimi etkinleştirir **Trial converted** olayı ise standart abonelik başladığında oluşturulur. <img src="/assets/shared/img_webhook_flows/Trial_Flow_with_Successful_Conversion.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Başarılı Dönüşüm Olmadan Deneme Akışı \{#trial-without-successful-conversion-flow\} Kullanıcı deneme süresi aboneliğe dönüşmeden iptal ederse, iptal anında şu olaylar oluşturulur: - **Trial renewal cancelled**: Deneme süresinin otomatik olarak aboneliğe dönüşmesi devre dışı bırakılır - **Access level updated**: Access level yenileme devre dışı bırakılır Kullanıcı, deneme süresinin sonuna kadar erişimine devam eder; bu sürenin bitişinde ise denemenin sona erdiğini işaretleyen **Trial expired** olayı oluşturulur. <img src="/assets/shared/img_webhook_flows/Trial_Flow_without_Successful_Conversion.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Süresi Dolmuş Deneme Sonrası Abonelik Yeniden Etkinleştirme Akışı \{#subscription-reactivation-after-expired-trial-flow\} Bir deneme süresi (faturalandırma sorunu veya iptal nedeniyle) sona ererse ve kullanıcı daha sonra bir abonelik satın alırsa, şu olaylar oluşturulur: - Kullanıcıya erişim vermek için **Access level updated** - **Trial converted** Deneme ile abonelik arasında bir boşluk olsa bile Adapty, `vendor_original_transaction_id` kullanarak ikisini birbirine bağlar. Bu dönüşüm, sıfır fiyatlı bir denemeyle başlayan kesintisiz bir işlem zincirinin parçası olarak değerlendirilir. Bu nedenle **Subscription started** yerine **Trial converted** olayı oluşturulur. <img src="/assets/shared/img_webhook_flows/Subscription_Reactivation_Flow_after_Expired_Trial.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Ürün Değişiklikleri \{#product-changes\} Bu bölüm, aktif aboneliklerde yapılan değişiklikleri kapsar; yükseltmeler, düşürmeler veya başka bir gruptan ürün satın alımları gibi. ### Anlık Ürün Değişikliği Akışı \{#immediate-product-change-flow\} Bir kullanıcı ürün değiştirdiğinde, abonelik sona ermeden önce bu değişiklik sistemde anlık olarak uygulanabilir (çoğunlukla bir ürünün yükseltilmesi veya değiştirilmesi durumunda). Bu durumda, ürün değişikliği anında: - Access level değişir ve iki **Access level updated** olayı oluşturulur: 1. Birinci ürüne erişimi kaldırmak için. 2. İkinci ürüne erişim vermek için. - Eski abonelik sona erer ve iade yapılır (**Subscription refunded** olayı `cancellation_reason` = `upgraded` ile oluşturulur). Dikkat: **Subscription expired (churned)** olayı oluşturulmaz; bunun yerine **Subscription refunded** olayı kullanılır. - Yeni abonelik başlar (yeni ürün için **Subscription started** olayı oluşturulur). <img src="/assets/shared/img_webhook_flows/Immediate_Product_Change_Flow_Upgrade.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Kullanıcı aboneliğini düşürürse, ilk abonelik ödenen süre sonuna kadar geçerliliğini korur ve sona erdiğinde yeni, daha düşük kademeli abonelikle değiştirilir. Bu durumda, yalnızca otomatik yenilemeyi devre dışı bırakmak için **Access level updated** eventi hemen oluşturulur. Diğer tüm eventler, aboneliğin fiilen değiştirildiği anda oluşturulur: - İkinci ürüne erişim vermek için yeni bir **Access level updated** eventi oluşturulur. - İlk ürünün aboneliğini sonlandırmak için **Subscription expired (churned)** eventi oluşturulur. - Yeni ürün için yeni bir abonelik başlatmak amacıyla **Subscription started** eventi oluşturulur. <img src="/assets/shared/img_webhook_flows/Delayed_Product_Change_Downgrade.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Gecikmeli Ürün Değişim Akışı \{#delayed-product-change-flow\} Kullanıcının ürünü abonelik yenileme anında değiştirdiği bir varyant da mevcuttur. Bu varyant bir öncekine çok benzer: eski ürün için otomatik yenilemeyi devre dışı bırakmak amacıyla tek bir **Access level updated** eventi hemen oluşturulur. Diğer tüm eventler, kullanıcının aboneliği değiştirdiği ve bu değişikliğin sistemde yansıtıldığı anda oluşturulur: - İkinci ürüne erişim vermek için yeni bir **Access level updated** olayı oluşturulur. - Birinci ürünün aboneliğini sona erdirmek için **Subscription expired (churned)** olayı oluşturulur. - Yeni ürün için yeni bir abonelik başlatmak amacıyla **Subscription started** olayı oluşturulur. <img src="/assets/shared/img_webhook_flows/Product_Change_on_Renewal_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Ödeme Sorunu Sonuç Akışı \{#billing-issue-outcome-flow\} Deneme süresini dönüştürme veya aboneliği yenileme girişimleri bir ödeme sorunu nedeniyle başarısız olursa, bundan sonra ne olacağı ek sürenin etkin olup olmadığına bağlıdır. Ek süre etkinken ödeme başarılı olursa deneme süresi dönüşür ya da abonelik yenilenir. Başarısız olursa uygulama mağazası kullanıcıyı abonelik için ücretlendirmeye çalışmaya devam eder; yine başarısız olursa uygulama mağazası deneme süresini veya aboneliği kendisi sonlandırır. Bu nedenle, ödeme sorununun yaşandığı anda Adapty'de aşağıdaki olaylar oluşturulur: - **Billing issue detected** - **Entered grace period** (ek süre etkinleştirilmişse) - **Access level updated** (ek süre sonuna kadar erişim sağlamak için) Ödeme daha sonra başarılı olursa, Adapty bir **Trial converted** veya **Subscription renewed** olayı kaydeder ve kullanıcı erişimini kaybetmez. Ödeme sonunda başarısız olur ve uygulama mağazası aboneliği iptal ederse, Adapty şu olayları oluşturur: - **Trial expired** veya **Subscription expired (churned)** — `cancellation_reason: billing_error` ile - **Access level updated** (kullanıcının erişimini iptal etmek için) <img src="/assets/shared/img_webhook_flows/Billing_Issue_Outcome_Flow_with_Grace_Period.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ek süre olmadan, Fatura Yeniden Deneme Süresi (uygulama mağazasının kullanıcıdan ücret almayı denemeye devam ettiği süre) hemen başlar. Ek süre sonuna kadar ödeme hiçbir zaman başarılı olmazsa, akış aynıdır: uygulama mağazası aboneliği otomatik olarak sonlandırdığında aynı olaylar oluşturulur: - `cancellation_reason` değeri `billing_error` olan **Trial expired** veya **Subscription expired (churned)** olayı - Kullanıcının erişimini iptal etmek için **Access level updated** <img src="/assets/shared/img_webhook_flows/Billing_Issue_Outcome_Flow_without_Grace_Period.webp" style={{ border: 'none', /* kenarlık genişliği ve rengi */ width: '700px', /* resim genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalama hizalama */ }} /> ## Kullanıcı Hesapları Arasında Satın Almaları Paylaşma Akışları \{#sharing-purchases-across-user-accounts-flows\} Bir <InlineTooltip tooltip="Customer User ID">[iOS](identifying-users#set-customer-user-id-on-configuration), [Android](android-identifying-users#setting-customer-user-id-on-configuration), [React Native](react-native-identifying-users#setting-customer-user-id-on-configuration), [Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration) ve [Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip>, zaten farklı bir <InlineTooltip tooltip="Customer User ID">[iOS](identifying-users#set-customer-user-id-on-configuration), [Android](android-identifying-users#setting-customer-user-id-on-configuration), [React Native](react-native-identifying-users#setting-customer-user-id-on-configuration), [Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration) ve [Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip>'ye bağlı bir aboneliği geri yüklemeye veya uzatmaya çalıştığında, Adapty'nin **Sharing paid access between user accounts** ayarı erişimin nasıl yönetileceğini belirler. Akış, seçilen seçeneğe göre değişir. :::note Apple Family Sharing işlemleri (`in_app_ownership_type=FAMILY_SHARED`) için yalnızca **Access level updated** eventi tetiklenir — aşağıdaki ürün bazlı abonelik eventleri tetiklenmez. Tam event matriksi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. ::: :::note Bir kullanıcı **Restore Purchases** butonuna dokunduğunda zaten aynı profilde erişimi varsa, geri yükleme işlemi hiçbir şey yapmaz ve hiçbir webhook eventi tetiklenmez. Bu bölümdeki eventler yalnızca erişim gerçekten profiller arasında aktarıldığında tetiklenir. ::: İkinci bir profilin mevcut bir aboneliği talep ettiğinde hangi olayların tetiklendiğini bir bakışta görmek için bu matrisi kullanın. Aşağıdaki bölümler her akış için tam JSON yükünü göstermektedir. | Olay | Etkin (varsayılan) | Erişimi yeni kullanıcıya aktar | Devre dışı | | --- | --- | --- | --- | | Yeni profil: **Access level updated** (`is_active=true`) | Tetiklenir | Tetiklenir | Tetiklenmez | | Eski profil: **Access level updated** (`is_active=false`) | Tetiklenmez — her iki profil de erişimi korur | Yeni tanımlanan cihaz işlemi yaydığında tetiklenir | Tetiklenmez — orijinal profil erişimi korur | | Yeni olayın `profiles_sharing_access_level` alanı | Access level'ı paylaşan diğer profilleri listeler | `null` | Uygulanamaz — olay tetiklenmez | Aktarılan bir abonelikte yenilemeler, iadeler ve süresi dolmalar; access level'ı o an elinde bulunduran profil üzerinde `subscription_renewed`, `subscription_refunded` ve `subscription_expired` olaylarını tetiklemeye devam eder. Aktarım olayının kendisi `subscription_started` olayı göndermez; çünkü yeni bir işlem kaydedilmez — yalnızca attribution değişir. Her mod için sözleşme ayrıntılarına bakmak isterseniz [Pratik referans](sharing-paid-access-between-user-accounts#practical-reference) bölümüne göz atın. ### Yeni Kullanıcıya Erişim Transferi \{#transfer-access-to-new-user-flow\} Önerilen seçenek, access level'ı yeni kullanıcıya aktarmaktır. Bu yaklaşım, tutarlı analitik için orijinal kullanıcının işlem geçmişini korur. Yalnızca 2 adet **Access level updated** olayı oluşturulur: 1. birinci kullanıcının erişimini kaldırmak için 2. ikinci kullanıcıya erişim vermek için <img src="/assets/shared/img_webhook_flows/Transfer_Access_to_New_User_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu senaryoda oluşturulan olaylardaki access level atama ve aktarımıyla ilgili alanların dökümü şöyledir: - **Kullanıcı A: Access level güncellendi (Kullanıcı A uygulamada bir abonelik satın aldığında gönderilir)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null } ``` - **User A: Access level güncellendi (uygulama yeniden yüklenip User B giriş yaptığında ve User A'nın erişimi iptal edildiğinde gönderilir)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": false, }, "profiles_sharing_access_level": null } ``` - **Kullanıcı B: Access level güncellendi (Kullanıcı B giriş yaptığında ve erişim verildiğinde gönderilir)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000001", "customer_user_id": UserB, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null } ``` ### Kullanıcılar Arasında Paylaşılan Erişim Akışı \{#shared-access-between-users-flow\} Bu seçenek, aynı Apple/Google kimliğiyle oturum açılmış cihazlardaki birden fazla kullanıcının aynı access level'ı paylaşmasına olanak tanır. Bu özellik, kullanıcının uygulamayı yeniden yükleyip farklı bir e-posta ile giriş yaptığında önceki satın alımına erişimini kaybetmemesi için kullanışlıdır. Bu seçenek sayesinde, birden fazla tanımlı kullanıcı aynı access level'ı paylaşabilir. Access level paylaşılırken tüm işlemler, eksiksiz işlem geçmişi ve analitik verilerinin korunması amacıyla orijinal <InlineTooltip tooltip="Müşteri Kullanıcı Kimliği">[iOS](identifying-users#set-customer-user-id-on-configuration), [Android](android-identifying-users#setting-customer-user-id-on-configuration), [React Native](react-native-identifying-users#setting-customer-user-id-on-configuration), [Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration) ve [Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip> altında kaydedilir. Dolayısıyla yalnızca 1 olay oluşturulur: İkinci kullanıcıya erişim vermek için **Access level updated**. <img src="/assets/shared/img_webhook_flows/Share_Access_Between_Users_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu senaryoda oluşturulan olaylarda access level atama ve paylaşımıyla ilgili alanların ayrıntılı açıklaması: **Kullanıcı B: Access level updated (Kullanıcı B giriş yaptığında ve erişim verildiğinde gönderilir)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": [ { "profile_id": "00000000-0000-0000-0000-000000000001, "customer_user_id": UserB } ] } ``` ### Erişimin Kullanıcılar Arasında Paylaşılmadığı Akış \{#access-not-shared-between-users-flow\} Bu seçenekte, access level'ı ilk alan kullanıcı profili bunu kalıcı olarak korur. Satın almaların tek bir <InlineTooltip tooltip="Customer User ID">[iOS](identifying-users#set-customer-user-id-on-configuration), [Android](android-identifying-users#setting-customer-user-id-on-configuration), [React Native](react-native-identifying-users#setting-customer-user-id-on-configuration), [Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration) ve [Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip>'a bağlı olması gerektiğinde bu seçenek idealdir. <img src="/assets/shared/img_webhook_flows/Share_Access_Between_Users_Disabled_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: event-statuses --- --- title: "Entegrasyon etkinlik durumları" description: "" --- Adapty, teslim edilebilirliği HTTP durum koduna göre belirler; `200-399` aralığı dışındaki her yanıtı başarısız kabul eder. Entegrasyon etkinliklerinin durumunu Adapty Kontrol Paneli'ndeki **Event List** bölümünde takip edebilirsiniz. Sistem, belirli bir etkinlik türü ilgili entegrasyon için açık olup olmadığına bakılmaksızın, etkinleştirilmiş tüm entegrasyonların durumlarını gösterir. - Siyah: Etkinlik başarıyla gönderildi. - <span style={{ color: 'grey' }}>Gri:</span> Etkinlik türü bu entegrasyon için devre dışı. - <span style={{ color: 'red' }}>Kırmızı:</span> Dikkat gerektiren bir entegrasyon sorunu var. Başarısız etkinlikler hakkında daha fazla bilgi için entegrasyon adının üzerine gelin; belirli hata bilgilerini içeren bir ipucu görüntülenir. <img src="/assets/shared/img/event-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Event Feed**, performansı optimize etmek amacıyla yalnızca son iki haftanın verilerini gösterir. Bu sınırlama, sayfa yükleme hızını artırır ve kullanıcıların etkinlikleri daha kolay gezinip analiz etmesini sağlar. --- # File: adjust --- --- title: "Adjust" description: "Daha iyi abonelik takibi ve analitik için Adjust'ı Adapty ile bağlayın." --- [Adjust](https://www.adjust.com/), pazarlama kampanyalarından veri toplayıp sunan önde gelen Mobil Ölçüm Ortağı (MMP) platformlarından biridir. Bu sayede şirketler kampanya performanslarını takip edebilir. Adapty, mağazalardan gelen [abonelik etkinliklerini](events) tek bir yerden takip etmenizi sağlayan eksiksiz bir veri seti sunar. Adapty sayesinde abonelerinizin davranışlarını kolayca görebilir, neyi sevdiklerini öğrenebilir ve bu bilgileri hedefli ve etkili bir şekilde iletişim kurmak için kullanabilirsiniz. Bu entegrasyon, abonelik etkinliklerini Adjust'ta takip etmenize ve kampanyalarınızın tam olarak ne kadar gelir ürettiğini analiz etmenize olanak tanır. Adapty ile Adjust arasındaki entegrasyon iki temel şekilde çalışır. 1. **Adapty, Adjust'tan attribution verisi alır** Adjust entegrasyonunu kurduktan sonra Adapty, Adjust'tan attribution verisi almaya başlar. Bu verilere kullanıcının profil sayfasından kolayca erişebilir ve görüntüleyebilirsiniz. <img src="/assets/shared/img/98769d9-CleanShot_2023-08-11_at_14.39.182x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Adapty, abonelik olaylarını Adjust'a gönderir** Adapty, entegrasyonunuzda yapılandırılmış tüm abonelik olaylarını Adjust'a gönderebilir. Böylece bu olayları Adjust kontrol panelinde takip edebilirsiniz. Bu entegrasyon, reklam kampanyalarınızın etkinliğini değerlendirmek için oldukça faydalıdır. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Adjust'a Bağlama \{#connect-adapty-to-adjust\} 1. Adapty Kontrol Paneli'ni açın ve [Integrations > Adjust](https://app.adapty.io/integrations/adjust) sayfasına gidin. 2. Sayfanın üstündeki geçiş düğmesini "on" konumuna getirin. 3. Alanları doldurun ve erişim kimlik bilgilerinizi girin. <img src="/assets/shared/img/5064125-CleanShot_2023-08-11_at_14.43.382x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adjust platformunda OAuth yetkilendirmeyi etkinleştirdiyseniz, iOS ve Android uygulamalarınız için entegrasyon sürecinde **OAuth Token** sağlamanız zorunludur. 4. Ardından iOS ve Android uygulamalarınız için **app token**'larını girin. Adjust kontrol panelinizi açtığınızda uygulamalarınızı göreceksiniz. <img src="/assets/shared/img/adjust-apps.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note iOS ve Android için farklı Adjust uygulamalarınız olabilir; bu nedenle Adapty'de bunlar için iki bağımsız bölüm bulunmaktadır. Yalnızca bir Adjust uygulamanız varsa aynı bilgileri iki alana da girebilirsiniz. ::: 5. Listeden uygulamanızı seçin ve **App Token**'ı kopyalayın. Token'ı Adapty kontrol panelindeki ilgili alana yapıştırın. <img src="/assets/shared/img/adjust-token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Etkinlikleri ve etiketleri yapılandırma \{#configure-events-and-tags\} Adjust, diğer platformlardan biraz farklı çalışır. Adjust kontrol panelinde etkinlikleri manuel olarak oluşturmanız, etkinlik token'larını almanız ve bunları Adapty'deki ilgili etkinliklere kopyalayıp yapıştırmanız gerekir. Dolayısıyla buradaki ilk adım, Adapty'nin göndermesini istediğiniz tüm etkinlikler için etkinlik token'larını bulmaktır. Bunun için: 1. Adjust kontrol panelinde uygulamanızı açın ve **Events** sekmesine geçin. <img src="/assets/shared/img/adjust-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. Etkinlik token'ını kopyalayın ve Adapty'ye yapıştırın. Kimlik bilgilerinin altında, Adapty'den Adjust'a gönderebileceğiniz üç grup etkinlik bulunmaktadır. Adapty'nin sunduğu etkinliklerin tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/adjust-event-token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty, sunucular arası entegrasyon aracılığıyla abonelik etkinliklerini Adjust'a gönderir. Bu sayede tüm abonelik etkinliklerini Adjust kontrol panelinizde görüntüleyebilir ve bunları edinim kampanyalarınızla ilişkilendirebilirsiniz. :::important Aşağıdakileri göz önünde bulundurun: - Adjust, 58 günden eski etkinlikleri desteklemiyor. Bu nedenle, 58 günden eski bir etkinliğiniz varsa Adapty onu Adjust'a gönderir; ancak etkinlik tarihi/saati geçerli zaman damgasıyla değiştirilir. - Adjust, IPv6'yı desteklemiyor. **App settings** bölümünde veya SDK etkinleştirme sırasında SDK'da IP toplamayı devre dışı bırakırsanız yalnızca bir backend IPv6 gönderilebilir ve izleme başarısız olabilir — IPv4 kullanıldığından emin olmak için SDK IP toplamayı etkin tutun. ::: ### Uygulamanızı Adjust ile bağlayın \{#connect-your-app-to-adjust\} Yukarıda açıklanan adımları tamamladıktan sonra, uygulamanıza aşağıdaki iki metodu ekleyin. Bu metodlar, uygulamanız ile Adjust arasındaki iletişimi sağlayacaktır: 1. **Abonelik verilerini Adjust'a göndermek için**: Adjust cihaz ID'sini `setIntegrationIdentifier()` SDK metoduna aktarın 2. **Adjust'tan attribution verisi almak için**: `updateAttribution()` SDK metoduyla attribution verisini güncelleyin Adjust 5.0 veya sonraki sürümler için aşağıdaki örneği kullanın: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers class AdjustModuleImplementation { func updateAdjustAdid() { Adjust.adid { adid in guard let adid else { return } // Adapty SDK 4.x Adapty.setIntegrationIdentifier(.adjustDeviceId(adid)) // Adapty SDK 3.x Adapty.setIntegrationIdentifier(key: "adjust_device_id", value: adid) } } func updateAdjustAttribution() { Adjust.attribution { attribution in guard let attribution = attribution?.dictionary() else { return } // Adapty SDK 4.x Adapty.updateAttribution(attribution, source: .adjust) // Adapty SDK 3.x Adapty.updateAttribution(attribution, source: "adjust") } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adjust.getAdid { adid -> if (adid == null) return@getAdid Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error -> if (error != null) { // handle the error } } } Adjust.getAttribution { attribution -> if (attribution == null) return@getAttribution Adapty.updateAttribution(attribution, "adjust") { error -> // handle the error } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adjust.getAdid(adid -> { if (adid == null) return; Adapty.setIntegrationIdentifier("adjust_device_id", adid, error -> { if (error != null) { // handle the error } }); }); Adjust.getAttribution(attribution -> { if (attribution == null) return; Adapty.updateAttribution(attribution, "adjust", error -> { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); Adjust.getAdid((adid) => { if (adid) adapty.setIntegrationIdentifier("adjust_device_id", adid); }); ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } await Adapty().setIntegrationIdentifier( key: "adjust_device_id", value: adid, ); final attributionData = await Adjust.getAttribution(); var attribution = Map<String, String>(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; await Adapty().updateAttribution(attribution, source: "adjust"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers // 1. To update ADID Adjust.GetAdid((adid) => { if (adid == null) { // handle the error return; } Adapty.SetIntegrationIdentifier("adjust_device_id", adid, (error) => { if (error != null) { // handle the error return; } }); }); // 2. To update Attribution // in your adjust configuration scope: adjustConfig.AttributionChangedDelegate = AttributionChangedCallback; public void AttributionChangedCallback(AdjustAttribution attributionData) { var attribution = new Dictionary<string, string>(); if (attributionData.TrackerToken != null) attribution["trackerToken"] = attributionData.TrackerToken; if (attributionData.TrackerName != null) attribution["trackerName"] = attributionData.TrackerName; if (attributionData.Network != null) attribution["network"] = attributionData.Network; if (attributionData.Adgroup != null) attribution["adgroup"] = attributionData.Adgroup; if (attributionData.Creative != null) attribution["creative"] = attributionData.Creative; if (attributionData.ClickLabel != null) attribution["clickLabel"] = attributionData.ClickLabel; if (attributionData.CostType != null) attribution["costType"] = attributionData.CostType; if (attributionData.CostAmount != null) attribution["costAmount"] = attributionData.CostAmount.ToString(); if (attributionData.CostCurrency != null) attribution["costCurrency"] = attributionData.CostCurrency; if (attributionData.FbInstallReferrer != null) attribution["fbInstallReferrer"] = attributionData.FbInstallReferrer; // you will probably need to install Newtonsoft.Json package, if not yet var attributionJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(attribution); Adapty.UpdateAttribution(attributionJsonString, "adjust", (error) => { if (error != null) { // handle the error } }); } ``` </TabItem> </Tabs> ## Etkinlik yapısı \{#event-structure\} Adapty, seçilen etkinlikleri [**Adjust Entegrasyon sayfasında**](https://app.adapty.io/integrations/adjust) **Events names** bölümünde yapılandırıldığı şekilde Adjust'a gönderir. Her etkinlik şu şekilde yapılandırılmıştır: ```json { "event_token": "EVENT_TOKEN_FROM_CONFIG", "app_token": "APP_TOKEN_FROM_CONFIG", "s2s": 1, "environment": "production", "created_at_unix": 1709294400, "currency": "USD", "revenue": 9.99, "customer_user_id": "user_12345", "external_device_id": "user_12345", "ip_address": "192.168.100.1", "user_agent": "Mozilla/5.0 (Linux; Android 14; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", "android_id": "875646c2-4a56-4211-8931-168532479006", "gps_adid": "875646c2-4a56-4211-8931-168532479006", "callback_params": "{\"integration_event_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"customer_user_id\":\"user_12345\",\"vendor_product_id\":\"com.example.app.yearly.premium\",\"transaction_id\":\"GPA.3312-4512-1100-55923\",\"original_transaction_id\":\"GPA.3312-4512-1100-55923\",\"store\":\"play_store\",\"store_country\":\"US\",\"price_usd\":9.99,\"proceeds_usd\":8.49,\"price_local\":9.99,\"proceeds_local\":8.49,\"net_revenue_usd\":8.49,\"net_revenue_local\":8.49,\"tax_amount_usd\":0.0,\"tax_amount_local\":0.0,\"consecutive_payments\":3,\"rate_after_first_year\":false}", "partner_params": "{\"integration_event_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"customer_user_id\":\"user_12345\",\"vendor_product_id\":\"com.example.app.yearly.premium\",\"transaction_id\":\"GPA.3312-4512-1100-55923\",\"original_transaction_id\":\"GPA.3312-4512-1100-55923\",\"store\":\"play_store\",\"store_country\":\"US\",\"price_usd\":9.99,\"proceeds_usd\":8.49,\"price_local\":9.99,\"proceeds_local\":8.49,\"net_revenue_usd\":8.49,\"net_revenue_local\":8.49,\"tax_amount_usd\":0.0,\"tax_amount_local\":0.0,\"consecutive_payments\":3,\"rate_after_first_year\":false}" } ``` Where | Parametre | Tür | Açıklama | |:---------------------|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------| | `app_token` | String | Entegrasyon ayarlarınızdaki Adjust App Token. | | `event_token` | String | Belirli bir Adapty olayına eşlenmiş Adjust Event Token. | | `s2s` | Integer | Sunucudan sunucuya (Server-to-Server) olay bayrağı. | | `environment` | String | `sandbox` veya `production`. | | `created_at_unix` | Integer | Olayın saniye cinsinden zaman damgası. | | `currency` | String | İşlem için para birimi kodu (ör. "USD"). Yalnızca gelir 0.001'i aştığında eklenir; Adjust, gelir ve para biriminin birlikte gönderilmesini gerektirir. | | `revenue` | Float | İşlem gelir tutarı. Yalnızca değer 0.001'i aştığında eklenir. Adjust negatif gelir değerlerini desteklemediğinden iade olayları gelir bilgisi olmadan gönderilir. | | `customer_user_id` | String | Kullanıcının Customer User ID'si. | | `external_device_id` | String | `customer_user_id` ile aynıdır. | | `ip_address` | String | Kullanıcının IP adresi (yalnızca IPv4). | | `user_agent` | String | Cihaz User Agent dizesi. | | `adid` | String | Adjust Device ID (biliniyorsa). | | `android_id` | String | **Yalnızca Android**. Google Advertising ID. | | `gps_adid` | String | **Yalnızca Android**. Google Advertising ID. | | `idfa` | String | **Yalnızca iOS**. ID for Advertisers. | | `idfv` | String | **Yalnızca iOS**. ID for Vendors. | | `callback_params` | String | Mevcut tüm [olay alanlarını](webhook-event-types-and-fields#for-most-event-types) içeren JSON dizesi. Yalnızca null olmayan alanlar dahil edilir. | | `partner_params` | String | `callback_params` ile aynıdır. | ## Sorun giderme \{#troubleshooting\} ### Gelir tutarsızlığı \{#revenue-discrepancy\} Adapty ile Adjust arasında gelir tutarsızlığı varsa, bunun nedeni muhtemelen tüm kullanıcılarınızın Adapty SDK'sını içeren uygulama sürümünü kullanmamasıdır. Veri tutarlılığını sağlamak için kullanıcılarınızı Adapty SDK'sının bulunduğu uygulama sürümüne güncellemeye zorlayabilirsiniz. --- # File: airbridge --- --- title: "Airbridge" description: "Pazarlama ve attribution verilerini takip etmek için Adapty'yi Airbridge ile entegre edin." --- [Airbridge](https://www.airbridge.io/), birden fazla cihaz, platform ve kanaldan toplanan verileri bir araya getirerek web siteleri ve mobil uygulamalar için entegre bir pazarlama performans analizi sunar. Airbridge'in Identity Resolution Engine'i sayesinde, web ve uygulama etkileşimlerinden elde edilen dağınık müşteri kimlik verilerini birleştirerek kişi bazlı tek bir kimlik oluşturabilir ve böylece daha doğru attribution elde edebilirsiniz. Adapty, mağazalardaki [abonelik etkinliklerini](events) tek bir yerde takip etmenizi sağlayan eksiksiz bir veri seti sunar. Adapty ile abonelerinizin davranışlarını kolayca gözlemleyebilir, tercihlerini öğrenebilir ve bu bilgileri hedefli ve etkili iletişim kurmak için kullanabilirsiniz. Adapty ile Airbridge arasındaki entegrasyon iki temel şekilde çalışır. 1. **Airbridge'den attribution verisi alma** Airbridge entegrasyonunu kurduktan sonra Adapty, Airbridge'den attribution verisi almaya başlar. Bu verilere kullanıcı sayfasından kolayca erişebilir ve görüntüleyebilirsiniz. 2. **Airbridge'e abonelik etkinlikleri gönderme** Adapty, entegrasyonunuzda yapılandırılan tüm abonelik etkinliklerini Airbridge'e gönderebilir. Bu sayede söz konusu etkinlikleri Airbridge kontrol panelinde takip edebilirsiniz. Bu entegrasyon, reklam kampanyalarınızın etkinliğini değerlendirmek için oldukça faydalıdır. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Airbridge'e bağlama \{#connect-adapty-to-airbridge\} Airbridge'i entegre etmek için [Integrations > Airbridge](https://app.adapty.io/integrations/airbridge) sayfasına gidin, geçiş düğmesini etkinleştirin ve gerekli alanları doldurun. Öncelikle Airbridge ve Adapty profilleriniz arasında bağlantı kurmak için kimlik bilgilerini girin. Airbridge uygulama adı ve Airbridge API token'ı zorunludur. <img src="/assets/shared/img/2b31d90-Untitled-1_1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Her ikisi de Airbridge kontrol panelinizde [Third-party Integrations > Adapty](https://app.airbridge.io/app/testad/integrations/third-party/adapty) bölümünde bulunabilir. <img src="/assets/shared/img/5a2f627-Screenshot_2023-02-21_at_11.19.29_AM.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty API token alanı, Adapty tarafında önceden oluşturulmuştur. Adapty API token değerini kopyalayarak Airbridge Kontrol Paneli'ndeki Adapty Authorization Token alanına yapıştırmanız gerekir. <img src="/assets/shared/img/ff422d1-CleanShot_2023-03-01_at_17.11.412x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Etkinlikleri ve etiketleri yapılandırma \{#configure-events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Airbridge'e gönderebileceğiniz üç etkinlik grubu bulunur. <img src="/assets/shared/img/eb4e3a9-CleanShot_2023-08-22_at_13.58.472x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> İhtiyaç duyduklarınızı etkinleştirmeniz yeterlidir. ### Uygulamanızı Airbridge'e bağlama \{#connect-your-app-to-airbridge\} Entegrasyon için `airbridge_device_id` değerini profil oluşturucuya iletmeniz ve aşağıdaki örnekte gösterildiği gibi `setIntegrationIdentifier` fonksiyonunu çağırmanız gerekir: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "airbridge_device_id", value: AirBridge.deviceUUID() ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback<String>() { override fun onSuccess(result: String) { Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error -> if (error != null) { // handle the error } } } override fun onFailure(throwable: Throwable) { } }) ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final deviceUUID = await Airbridge.state.deviceUUID; try { await Adapty().setIntegrationIdentifier( key: "airbridge_device_id", value: deviceUUID, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers try { const deviceId = await Airbridge.state.deviceUUID(); await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> `airbridgeDeviceId` hakkında daha fazla bilgi için [Airbridge belgelerine](https://help.airbridge.io/en/developers/airbridge-device-id-faq) bakabilirsiniz. Adapty'nin bir abonelik etkinliğinin ardından Airbridge attribution verilerini alması 24 saate kadar sürebilir. Adapty bu verileri kontrol panelinde anında görüntüler. ## Etkinlik yapısı \{#event-structure\} Adapty, seçilen etkinlikleri [**Airbridge Integration page**](https://app.adapty.io/integrations/airbridge) sayfasındaki **Events names** bölümünde yapılandırıldığı şekilde Airbridge'e gönderir. Her etkinlik şu şekilde yapılandırılmıştır: ```json { "user": { "externalUserID": "user_12345", "externalUserEmail": "user@example.com", "attributes": { "is_premium": true } }, "device": { "deviceUUID": "550e8400-e29b-41d4-a716-446655440000", "deviceModel": "iPhone 14 Pro", "osName": "iOS", "osVersion": "17.0.1", "locale": "en-US", "timezone": "America/New_York", "ifa": "00000000-0000-0000-0000-000000000000", "ifv": "00000000-0000-0000-0000-000000000000" }, "app": { "packageName": "com.example.app", "version": "1.2.3" }, "eventUUID": "d4f6f1f4-96fb-4a31-bafd-599fef77be90", "eventTimestamp": 1709294400000, "eventData": { "goal": { "category": "airbridge.subscribe", "customAttributes": { "isTrialConverted": true }, "semanticAttributes": { "transactionID": "GPA.3383-4699-1373-07113", "totalValue": 9.99, "currency": "USD", "period": "P1M", "isRenewal": true, "renewalCount": 2, "products": [ { "productID": "yearly.premium.6999", "name": "yearly.premium.6999", "position": 1 } ] } } } } ``` Parametreler: | Parametre | Tür | Açıklama | |:---------------------------------------------|:--------|:---------------------------------------------------------------------------------------| | `user` | Object | Kullanıcı bilgileri. | | `user.externalUserID` | String | Kullanıcının Customer User ID'si. | | `user.externalUserEmail` | String | Kullanıcının e-posta adresi (varsa). | | `user.attributes` | Object | Özel kullanıcı nitelikleri. | | `device` | Object | Cihaz bilgileri. | | `device.deviceUUID` | String | Airbridge Cihaz UUID'si. | | `device.deviceModel` | String | Cihaz modeli (örn. "iPhone 14 Pro"). | | `device.osName` | String | İşletim sistemi adı (örn. "iOS", "Android"). | | `device.osVersion` | String | İşletim sistemi sürümü. | | `device.ifa` | String | **Yalnızca iOS**. Reklamverenler için kimlik (ID for Advertisers). | | `device.ifv` | String | **Yalnızca iOS**. Satıcılar için kimlik (ID for Vendors). | | `device.gaid` | String | **Yalnızca Android**. Google Advertising ID. | | `app` | Object | Uygulama bilgileri. | | `app.packageName` | String | Uygulamanın paket adı / bundle ID'si. | | `app.version` | String | Uygulamanın sürümü. | | `eventUUID` | String | Adapty'deki etkinliğin benzersiz kimliği. | | `eventTimestamp` | Long | Etkinliğin milisaniye cinsinden zaman damgası. | | `eventData` | Object | Etkinlik ayrıntıları. | | `eventData.goal.category` | String | Airbridge etkinlik kategorisi (Adapty etkinliğinden eşlenir). | | `eventData.goal.semanticAttributes` | Object | Standart etkinlik nitelikleri. | | `...semanticAttributes.transactionID` | String | Mağaza İşlem Kimliği. | | `...semanticAttributes.totalValue` | Float | Gelir tutarı. | | `...semanticAttributes.currency` | String | Para birimi kodu (örn. "USD"). | | `...semanticAttributes.period` | String | ISO 8601 süre formatında abonelik dönemi (örn. "P1M"). | | `...semanticAttributes.isRenewal` | Boolean | İşlem bir yenileme ise `true`. | | `...semanticAttributes.renewalCount` | Integer | Başarılı yenileme sayısı. | | `...semanticAttributes.products` | Array | Etkinliğe dahil olan ürünlerin listesi. | | `...semanticAttributes.products[].productID` | String | Mağazadaki Ürün Kimliği (örn. "yearly.premium.6999"). | | `...semanticAttributes.products[].name` | String | `productID` ile aynıdır. | | `...semanticAttributes.products[].position` | Integer | Ürünün listedeki konumu (her zaman 1). | --- # File: apple-search-ads --- --- title: "Apple Ads" description: "Abonelik dönüşümlerini optimize etmek için Apple Ads'i Adapty ile entegre edin." --- :::important **App settings** içindeki Apple Ads entegrasyonu yalnızca temel analitik ve SplitMetrics Acquire ile Asapty entegrasyonları için kullanılır. [Adapty Ads Manager](adapty-ads-manager), ayrı bir bağlantı kullanır. Apple Ads hesabınızı [Adapty Ads Manager](adapty-ads-manager-get-started) üzerinden bağlayın. ::: Adapty, Apple Ads'ten attribution verisi almanıza ve kampanya ile anahtar kelime segmentasyonuyla metriklerinizi analiz etmenize yardımcı olur. Adapty, Apple Ads için attribution verilerini SDK ve AdServices Framework aracılığıyla otomatik olarak toplar. Apple Ads entegrasyonunu kurduktan sonra Adapty, Apple Ads'ten attribution verisi almaya başlar. Bu verilere profiller sayfasından kolayca erişip görüntüleyebilirsiniz. <img src="/assets/shared/img/ba4a3e9-CleanShot_2023-08-21_at_15.14.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Entegrasyonu Kurma \{#set-up-integration\} ### Adapty'yi AdServices framework'üne bağlama \{#connect-adapty-to-the-adservices-framework\} Apple Ads, [AdServices](https://developer.apple.com/documentation/adservices) aracılığıyla Adapty Kontrol Paneli'nde bazı yapılandırmalar gerektirir ve bunu uygulama tarafında da etkinleştirmeniz gerekir. AdServices framework'ü aracılığıyla Adapty üzerinden Apple Ads'i kurmak için şu adımları izleyin: #### 1. Adım: Genel anahtarı edinin \{#step-1-obtain-public-key\} Adapty Kontrol Paneli'nde [Settings -> Apple Ads](https://app.adapty.io/settings/apple-search-ads) sayfasına gidin. Önceden oluşturulmuş genel anahtarı (Adapty sizin için bir anahtar çifti sağlar) bulun ve kopyalayın. <img src="/assets/shared/img/baa5998-CleanShot_2023-08-21_at_14.55.542x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Apple Ads attribution için alternatif bir hizmet veya kendi çözümünüzü kullanıyorsanız, kendi özel anahtarınızı yükleyebilirsiniz. ::: #### Adım 2: Apple Ads'de kullanıcı yönetimini yapılandırın \{#step-2-configure-user-management-on-apple-ads\} [Apple Ads hesabınızda](https://ads.apple.com/app-store) **Settings > User Management** sayfasına gidin. Adapty'nin attribution verilerini çekebilmesi için başka bir Apple ID hesabını davet etmeniz ve bu hesaba API Account Manager erişimi vermeniz gerekir. Erişiminiz olan herhangi bir hesabı kullanabilir ya da bu amaç için yeni bir hesap oluşturabilirsiniz. Önemli olan nokta şudur: bu Apple ID ile Apple Ads'e giriş yapabilmeniz gerekir. <img src="/assets/shared/img/ec183b2-kdjsfldsfjkdsfdfd.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### Adım 3: API kimlik bilgileri oluşturun \{#step-3-generate-api-credentials\} Bir sonraki adım olarak, Apple Ads'e yeni eklenen hesapla giriş yapın. Apple Ads arayüzünde Settings -> API bölümüne gidin. Daha önce kopyaladığınız genel anahtarı ilgili alana yapıştırın. Yeni API kimlik bilgileri oluşturun. #### Adım 4: Adapty'yi Apple Ads kimlik bilgileriyle yapılandırın \{#step-4-configure-adapty-with-apple-ads-credentials\} Apple Ads ayarlarından Client ID, Team ID ve Key ID alanlarını kopyalayın. Adapty Kontrol Paneli'nde bu kimlik bilgilerini ilgili alanlara yapıştırın. <img src="/assets/shared/img/7356113-CleanShot_2023-08-21_at_15.08.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Uygulamanızı AdServices ağına bağlama \{#connect-your-app-to-the-adservices-network\} [AdServices framework kurulumunu](#connect-the-adservices-framework) tamamladıktan sonra Adapty, Apple Search Ad attribution verilerini otomatik olarak toplamaya başlar. Herhangi bir SDK kodu eklemenize gerek yoktur. iOS uygulamaları için bu attribution verisi **her zaman** diğer kaynaklardan gelen verilere göre öncelikli olacaktır. Bu davranış istenmiyor ise aşağıdaki talimatları kullanarak ASA attribution'ı *devre dışı bırakın*. ## Entegrasyonu devre dışı bırakma \{#disable-integration\} Apple Search Ads attribution'ını kapatmak için [**App Settings** -> **Apple Search Ads** sekmesini](https://app.adapty.io/settings/apple-search-ads) açın ve **Receive Apple Search Ads attribution** anahtarını kapatın. <img src="/assets/shared/img/asa-disable.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning Bunu devre dışı bırakmanın ASA analizlerinin tamamen durmasına yol açacağını unutmayın. Sonuç olarak, ASA artık analizlerde kullanılmayacak ve entegrasyonlara gönderilmeyecektir. Ayrıca SplitMetrics Acquire ve Asapty, doğru çalışmak için ASA attribution'a bağlı olduklarından işlevlerini yitirecektir. Bu değişiklikten önce alınan attribution verileri etkilenmeyecektir. ::: ## Kendi Anahtarlarınızı Yükleme \{#uploading-your-own-keys\} :::note İsteğe bağlı Bu adımlar Apple Ads attribution için zorunlu değildir; yalnızca Asapty gibi diğer hizmetlerle veya kendi çözümünüzle çalışmak için gereklidir. ::: ASA attribution için başka hizmetler ya da kendi çözümünüzü kullanıyorsanız kendi genel-özel anahtar çiftinizi kullanabilirsiniz. ### Adım 1 \{#step-1\} Terminal'de özel anahtar oluşturun ```text showLineNumbers title="Text" openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem ``` Adapty Settings -> Apple Ads bölümünden yükleyin (Upload private key butonu) ### Adım 2 \{#step-2\} Terminal'de genel anahtar oluşturun ```text showLineNumbers title="Text" openssl ec -in private-key.pem -pubout -out public-key.pem ``` Bu genel anahtarı, API Account Manager rolüne sahip hesabın Apple Ads ayarlarında kullanabilirsiniz. Böylece oluşturulan Client ID, Team ID ve Key ID değerlerini hem Adapty hem de diğer hizmetler için kullanabilirsiniz. --- # File: switch-from-appsflyer-s2s-api-2-to-3 --- --- title: "AppsFlyer S2S API 2'den 3'e Geçiş" description: "Adapty'de AppsFlyer S2S API 2'den 3'e yükseltin." --- [Resmi AppsFlyer What's New](https://support.appsflyer.com/hc/en-us/articles/20509378973457-Bulletin-Upgrading-the-AppsFlyer-S2S-API) sayfasına göre AppsFlyer, API kullanımını daha güvenli hale getirmek ve dolandırıcılığı azaltmak amacıyla uygulama içi etkinlikler için sunucudan sunucuya (S2S) API'sini yükseltti. Mevcut endpoint ileride kullanımdan kaldırılacak; bu nedenle geçişi şimdiden planlamaya başlamanızı öneririz. Adapty, AppsFlyer S2S API 3'ü destekler ve API 2'den sorunsuz bir geçiş sunar. Bu geçişin tek yönlü olduğunu unutmayın; değişikliği yaptıktan sonra API 2'ye geri dönemezsiniz. AppsFlyer S2S API 2'den 3'e geçmek için: 1. [AppsFlyer sitesini](https://www.appsflyer.com/home) açın ve giriş yapın. 2. Kontrol panelinin sol üst köşesinde **Hesap adınıza** tıklayın ve **Security Center**'ı seçin. <img src="/assets/shared/img/be299ea-appsflyer_security_center.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Manage your account security** penceresinde **Manage your AppsFlyer API and S2S tokens** düğmesine tıklayın. 4. S2S tokenınız yoksa **New token** düğmesine tıklayın. Zaten varsa 8. adıma geçin. <img src="/assets/shared/img/7934920-appsflyer_new_token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **New token** penceresinde token için bir ad girin. Bu ad yalnızca sizin referansınız içindir. 6. **Choose type** listesinden **S2S** seçeneğini seçin. 7. Yeni tokeni kaydetmek için **Create new token** düğmesine tıklamayı unutmayın. 8. **Tokens** penceresinde S2S tokenı kopyalayın. <img src="/assets/shared/img/d014c25-appsflyer_tokens.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. Adapty Kontrol Paneli'nde [**Integrations** -> **AppsFlyer**](https://app.adapty.io/integrations/appsflyer) bölümünü açın. 10. **AppsFlyer S2S API** alanında **API 3**'ü seçin. <img src="/assets/shared/img/c0b3e72-appsflyer_switch_API.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 11. Kopyaladığınız S2S anahtarını **Dev key for iOS** ve **Dev key for Android** alanlarına yapıştırın. 12. Geçişi onaylamak için **Save** düğmesine tıklayın. Bu işlemin ardından entegrasyonunuz anında AppsFlyer S2S API 3'e geçer ve yeni etkinlikleriniz şu URL'ye gönderilmeye başlar: `https://api3.appsflyer.com/inappevent`. --- # File: asapty --- --- title: "Asapty" description: "Asapty'yi ve Adapty'nin abonelik ekosistemindeki rolünü keşfedin." --- [Asapty](https://asapty.com/) entegrasyonunu kullanarak Search Ads kampanyalarınızı optimize edebilirsiniz. Adapty, abonelik olaylarını Asapty'ye gönderir; böylece Apple Search Ads attribution verilerine dayalı özel kontrol panelleri oluşturabilirsiniz. Bu entegrasyon, Adapty'ye herhangi bir attribution verisi eklemez; zira ihtiyacımız olan her şeyi doğrudan [ASA](apple-search-ads) üzerinden alıyoruz. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Asapty'ye bağlama \{#connect-adapty-to-asapty\} Asapty entegrasyonunu kurmak için Adapty kontrol panelinde [Integrations > Asapty](https://app.adapty.io/integrations/asapty) bölümüne gidin ve Asapty ID alanını doldurun. <img src="/assets/shared/img/895de2b-CleanShot_2023-08-14_at_18.57.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Asapty ID'nizi Asapty hesabınızdaki **Settings > General** bölümünde bulabilirsiniz. ### Olayları ve etiketleri yapılandırma \{#configure-events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Asapty'ye gönderebileceğiniz üç grup olay yer almaktadır. İhtiyacınız olanları etkinleştirmeniz yeterli. Adapty'nin sunduğu olayların tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/58ddf41-CleanShot_2023-08-15_at_15.11.072x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Asapty'nin sağladığı varsayılan olay adlarını kullanmanızı öneririz. Ancak ihtiyaçlarınıza göre olay adlarını değiştirebilirsiniz. ### Uygulamanızı Asapty'ye bağlama \{#connect-your-app-to-asapty\} Yukarıdaki adımları tamamladıktan sonra Adapty, attribution verilerini Asapty'den otomatik olarak alır. Uygulama kodunuzda attribution verilerini açıkça talep etmenize gerek yoktur. Daha doğru attribution verileri için Asapty'yi her olayın verisiyle birlikte `customerUserId` paylaşacak şekilde yapılandırın. ## Asapty olay yapısı \{#asapty-event-structure\} Adapty, olayları sorgu parametreleri aracılığıyla GET isteğiyle Asapty'ye gönderir. Her olay URL'si şu şekilde görünür: ``` https://asapty.com/_api/mmpEvents/?source=adapty&asaptyid=a1b2c3d4&keywordid=12345&adgroupid=67890&campaignid=11223&conversiondate=1709294400000&event_name=subscription_renewed&install_time=1709100000&app_name=MyApp&json=%7B%22af_revenue%22%3A%229.99%22%2C%22af_currency%22%3A%22USD%22...%7D ``` Sorgu parametreleri: | Parametre | Tür | Açıklama | |:-----------------|:-------|:--------------------------------------------------------------| | `source` | String | Her zaman "adapty" değerini alır. | | `asaptyid` | String | Kimlik bilgilerinizdeki Asapty ID. | | `keywordid` | String | Apple Search Ads Anahtar Kelime ID'si (varsa). | | `adgroupid` | String | Apple Search Ads Reklam Grubu ID'si (varsa). | | `campaignid` | String | Apple Search Ads Kampanya ID'si (varsa). | | `conversiondate` | Long | Olayın **milisaniye** cinsinden zaman damgası. | | `event_name` | String | Olay adı (Adapty olayından eşlenen). | | `install_time` | Long | Kurulumun saniye cinsinden zaman damgası. | | `app_name` | String | Adapty'deki uygulama başlığı (varsa). | | `json` | String | Olay ayrıntılarını içeren URL kodlu JSON dizesi (aşağıya bakın). | `json` parametresi, aşağıdaki alanları içeren URL kodlu bir JSON dizesidir: | Parametre | Tür | Açıklama | |:--------------------------|:-------|:----------------------------------------------------| | `af_revenue` | String | Dize olarak gelir miktarı. | | `af_currency` | String | Para birimi kodu (ör. "USD"). | | `transaction_id` | String | Mağaza İşlem ID'si. | | `original_transaction_id` | String | Orijinal Mağaza İşlem ID'si. | | `purchase_date` | Long | Milisaniye cinsinden satın alma zaman damgası. | | `original_purchase_date` | Long | Milisaniye cinsinden orijinal satın alma zaman damgası. | | `environment` | String | `Production` veya `Sandbox`. | | `vendor_product_id` | String | Mağazadaki Ürün ID'si. | | `profile_country` | String | Kullanıcının IP'sine göre ülke kodu. | | `store_country` | String | Kullanıcının mağaza ülke kodu. | ## Sorun giderme \{#troubleshooting\} - Adapty'de [Apple Search Ads](apple-search-ads) yapılandırdığınızdan ve [kimlik bilgilerini yüklediğinizden](https://app.adapty.io/settings/apple-search-ads) emin olun; bunlar olmadan Asapty çalışmaz. - Yalnızca ayrıntılı, organik olmayan ASA attribution verisine sahip profiller olaylarını Asapty'ye iletebilir. Attribution yeterli değilse "The user profile is missing the required integration data." mesajını görürsünüz. - Entegrasyon yapılandırılmadan önce oluşturulan profiller olaylarını Asapty'ye iletamaz. - Doğru kuruluma rağmen Adapty entegrasyonu çalışmıyorsa [**App Settings** -> **Apple Search Ads** sekmesinde](https://app.adapty.io/settings/apple-search-ads) **Receive Apple Search Ads attribution in Adapty** geçişinin etkin olduğundan emin olun. --- # File: branch --- --- title: "Branch" description: "Branch'i Adapty ile entegre ederek derin bağlantıları ve uygulama dönüşümlerini takip edin." --- [Branch](https://www.branch.io/), müşterilerin farklı cihazlar, kanallar ve platformlar arasında kullanıcılara ulaşmasını, onlarla etkileşim kurmasını ve sonuçları değerlendirmesini sağlar. Tüm cihazlar, kanallar ve platformlarda sorunsuz çalışan özel bağlantılar aracılığıyla mobil geliri artırmak için tasarlanmış kullanıcı dostu bir platformdur. Adapty, mağazalardan gelen [abonelik etkinliklerini](events) tek bir yerde takip etmenizi sağlayan eksiksiz bir veri seti sunar. Adapty ile abonelerinizin davranışlarını kolayca gözlemleyebilir, tercihlerini öğrenebilir ve bu bilgileri hedefli ve etkili bir şekilde iletişim kurmak için kullanabilirsiniz. Adapty ile Branch arasındaki entegrasyon iki ana şekilde çalışır. 1. **Branch'ten attribution verisi alma** Entegrasyonu kurduktan sonra Adapty, Branch'ten attribution verisi almaya başlar. Bu verilere kullanıcının profil sayfasından kolayca erişip görüntüleyebilirsiniz. <img src="/assets/shared/img/49f4aa7-CleanShot_2023-08-11_at_17.36.072x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Branch'e abonelik olayları gönderme** Adapty, entegrasyonunuzda yapılandırılan tüm abonelik olaylarını Branch'e gönderebilir. Böylece bu olayları Branch kontrol panelinde takip edebilirsiniz. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Branch'e bağlama \{#connect-adapty-to-branch\} Branch entegrasyonu için Adapty Kontrol Paneli'nde [Integrations > Branch](https://app.adapty.io/integrations/branch) bölümüne gidin, geçiş düğmesini açık konuma getirin ve gerekli alanları doldurun. <img src="/assets/shared/img/817a051-CleanShot_2023-08-11_at_15.54.372x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Branch Key** değerini almak için Branch [Hesap Ayarları](https://dashboard.branch.io/account-settings/profile) sayfasını açın ve **Branch Key** alanını bulun. Bu değeri Adapty Kontrol Paneli'ndeki **Key test** (Sandbox için) veya **Key live** (Prodüksiyon için) alanına girin. Branch'te uygun anahtarı kullanmak için Live ve Test ortamları arasında geçiş yapın. <img src="/assets/shared/img/130e58b-CleanShot_2023-08-11_at_15.24.162x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Etkinlikleri ve etiketleri yapılandırma \{#configure-events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Branch'e gönderebileceğiniz üç grup etkinlik yer alır. İhtiyaç duyduklarınızı açmanız yeterli. Adapty'nin sunduğu etkinliklerin tam listesine [buradan](events) ulaşabilirsiniz. Etkinlikleri Gelir (Apple/Google payı düşüldükten sonra) veya yalnızca ciro olarak gönderebilirsiniz. Ayrıca raporlamayı kullanıcının para biriminden yapılacak şekilde ayarlayabilirsiniz. <img src="/assets/shared/img/a645cf8-CleanShot_2023-08-11_at_15.18.282x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin sunduğu varsayılan etkinlik adlarını kullanmanızı öneririz. Ancak ihtiyacınıza göre etkinlik adlarını değiştirebilirsiniz. Adapty, abonelik etkinliklerini sunucudan sunucuya entegrasyon aracılığıyla Branch'e gönderir. Bu sayede tüm abonelik etkinliklerini Branch kontrol panelinizde görüntüleyebilir ve edinim kampanyalarınızla ilişkilendirebilirsiniz. ### Uygulamanızı Branch'e bağlayın \{#connect-your-app-to-branch\} 1. Bağlantıyı başlatmak için `.setIntegrationIdentifier()` SDK metodunu çağırın. Branch Identity ID'nizi `customerUserId` parametresine iletebilirsiniz. :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.branchId(<BRANCH_IDENTITY_ID>)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "branch_id", value: <BRANCH_IDENTITY_ID> ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // login and update attribution and identifier Branch.getAutoInstance(this) .setIdentity("YOUR_USER_ID") { referringParams, error -> referringParams?.let { data -> Adapty.updateAttribution(data, "branch") { error -> if (error != null) { //handle the error } } } } // logout Branch.getAutoInstance(context).logout() ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers import 'package:flutter_branch_sdk/flutter_branch_sdk.dart'; FlutterBranchSdk.setIdentity('YOUR_USER_ID'); ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers Branch.setIdentity("your user id"); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers import branch from 'react-native-branch'; branch.setIdentity('YOUR_USER_ID'); ``` </TabItem> </Tabs> 2. Attribution verisini kaydetmek için `.updateAttribution()` metodunu kullanın. Branch kullanıcı ID'sini bir önceki adımda belirtmediyseniz, burada `networkUserId` parametresine geçirin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers class YourBranchImplementation { func initializeBranch() { // Branch iOS SDK'nın başlatma metodundan aldığınız attribution'ı Adapty'ye iletin. Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in if let data { // Adapty SDK 4.x Adapty.updateAttribution(data, source: .branch) // Adapty SDK 3.x Adapty.updateAttribution(data, source: "branch") } } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers //everything is in the above snippet for Android ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers try { await Adapty().setIntegrationIdentifier( key: "branch_id", value: <BRANCH_IDENTITY_ID>, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; Branch.initSession(delegate(Dictionary<string, object> parameters, string error) { string attributionString = JsonUtility.ToJson(parameters); Adapty.UpdateAttribution( attributionString, "branch", (error) => { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { adapty.updateAttribution(params, "branch"); }, }); ``` </TabItem> </Tabs> ## Etkinlik yapısı \{#event-structure\} Adapty, seçilen etkinlikleri [**Branch Entegrasyon sayfasındaki**](https://app.adapty.io/integrations/branch) **Events names** bölümünde yapılandırıldığı şekilde Branch'e gönderir. Her etkinlik şu yapıya sahiptir: ```json { "branch_key": "key_live_kaFuWw8WvY7n1ss7...", "name": "PURCHASE", "user_data": { "os": "iOS", "developer_identity": "user_12345", "country": "US", "ip": "192.168.100.1", "idfa": "00000000-0000-0000-0000-000000000000", "idfv": "00000000-0000-0000-0000-000000000000", "aaid": "00000000-0000-0000-0000-000000000000" }, "event_data": { "transaction_id": "GPA.3383-4699-1373-07113", "revenue": 9.99, "currency": "USD" }, "custom_data": { "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383-4699-1373-07113", "store": "play_store", "environment": "production" } } ``` Parametreler: | Parametre | Tür | Açıklama | |:-------------------------------|:-------|:---------------------------------------------------------------------------------------------------------------------------------------------| | `branch_key` | String | Branch Key'iniz. | | `name` | String | Branch etkinlik adı (Adapty etkinliğinden eşlenen, örn. "PURCHASE"). | | `user_data` | Object | Kullanıcı bilgileri. | | `user_data.os` | String | "Android" veya "iOS". | | `user_data.developer_identity` | String | Kullanıcının Customer User ID'si. | | `user_data.country` | String | Kullanıcının IP adresine göre belirlenen ülke kodu. | | `user_data.ip` | String | Kullanıcının IP adresi. | | `user_data.idfa` | String | **Yalnızca iOS**. Reklamverenler için ID (ID for Advertisers). | | `user_data.idfv` | String | **Yalnızca iOS**. Satıcılar için ID (ID for Vendors). | | `user_data.aaid` | String | **Yalnızca Android**. Google Reklam ID'si. | | `event_data` | Object | Standart etkinlik metrikleri (yalnızca PURCHASE ve benzeri etkinliklerde bulunur). | | `event_data.transaction_id` | String | Mağaza İşlem ID'si. | | `event_data.revenue` | Float | Gelir tutarı. | | `event_data.currency` | String | Para birimi kodu (örn. "USD"). | | `custom_data` | Object | Ayrıntılı etkinlik nitelikleri (mevcut tüm [etkinlik alanlarını](webhook-event-types-and-fields#for-most-event-types) içerir). | --- # File: facebook-ads --- --- title: "Facebook Ads" description: "Etkili abonelik pazarlaması için Facebook Ads'i Adapty ile entegre edin." --- Facebook Ads entegrasyonu sayesinde uygulama istatistiklerinizi Meta Analytics üzerinden kolayca takip edebilirsiniz. Adapty, Meta Ads Manager'a etkinlik göndererek aboneliklere dayalı benzer kitleler oluşturmanıza ve daha iyi dönüşler elde etmenize yardımcı olur. Bu sayede reklamlarınızın aboneliklerden ne kadar gelir sağladığını doğru biçimde görebilirsiniz. Adapty ile Facebook Ads entegrasyonu şu şekilde çalışır: Adapty, entegrasyonunuzda yapılandırılan tüm abonelik etkinliklerini Facebook Ads'e gönderir. Bu entegrasyon, reklam kampanyalarınızın etkinliğini değerlendirmek için oldukça kullanışlıdır. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Facebook Ads'e bağlama \{#connect-adapty-to-facebook-ads\} Facebook Ads entegrasyonunu kurmak ve uygulama metriklerinizi analiz etmek için Meta Analytics entegrasyonunu ayarlayabilirsiniz. Meta Ads Manager'a etkinlik göndererek yenileme gibi abonelik etkinliklerine dayalı benzer kitleler oluşturabilirsiniz. Bu entegrasyonu yapılandırmak için Adapty Kontrol Paneli'nde [Integrations > Facebook Ads](https://app.adapty.io/integrations/facebookanalytics) bölümüne gidin ve gerekli kimlik bilgilerini girin. :::note Facebook Ads entegrasyonunun yalnızca ATT onayı vermiş kullanıcılar için iOS 14.5 ve üzeri sürümlerde çalıştığını lütfen unutmayın. ::: <img src="/assets/shared/img/fd84ddf-CleanShot_2023-08-15_at_15.45.442x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. App ID'yi bulmak için [App Store Connect](https://appstoreconnect.apple.com/)'te uygulamanızın sayfasını açın, **General** bölümündeki **App Information** sayfasına gidin ve ekranın sol alt kısmında **Apple ID**'yi bulun. 2. [Meta for Developers](https://developers.facebook.com/) platformunda bir uygulamanız olması gerekir. Uygulamanıza giriş yapın ve gelişmiş ayarları bulun. **App ID**'yi üst bilgi kısmında görebilirsiniz. <img src="/assets/shared/img/4b326c4-001563-August-23-4tO3JVso.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Meta Ads Manager'da gelirin çift sayılmasını önlemek için Meta SDK yapılandırmanızda istemci taraflı izlemeyi devre dışı bırakın. Bu ayarı Meta Developer Console'da **App Settings > Advanced Settings** altında bulabilirsiniz. **Log in-app events automatically** seçeneğini "No" olarak ayarlayın. Bu sayede gelir etkinlikleri yalnızca Adapty'nin entegrasyonu üzerinden izlenir. Yükleme ve kullanım etkinliklerini izlemek için kodunuzda Meta SDK'yı etkinleştirmeniz gerekir. Platforma göre uygulama ayrıntılarını Meta SDK belgelerinde bulabilirsiniz: - [iOS SDK](https://developers.facebook.com/docs/ios/getting-started) - [Android SDK](https://developers.facebook.com/docs/android/getting-started) - [Unity SDK](https://developers.facebook.com/docs/unity/getting-started/canvas) <img src="/assets/shared/img/c4eb8eb-001565-August-23-483KKBbC.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu entegrasyonu Android uygulamalarıyla da kullanabilirsiniz. **App Settings** bölümünde Android SDK yapılandırmasını ayarladıysanız yalnızca **Facebook App ID**'yi girmek yeterlidir. ### Etkinlikleri ve etiketleri yapılandırma \{#configure-events-and-tags\} Facebook Ads entegrasyonunun özellikle reklam kampanyaları için Meta kullanan ve bu kampanyaları müşteri davranışlarına göre optimize eden şirketlere yönelik olduğunu lütfen unutmayın. Bu entegrasyon, optimizasyon amacıyla Meta'nın standart etkinliklerini destekler. Dolayısıyla Meta Ads entegrasyonunda etkinlik adını değiştirmek mümkün değildir. Adapty, müşteri etkinliklerinizi doğru analiz için ilgili Meta etkinlikleriyle otomatik olarak eşleştirir. | Adapty etkinliği | Meta Ads etkinliği | | :---------------------------- | :-------------------------- | | Subscription initial purchase | Subscribe | | Subscription renewed | Subscribe | | Subscription cancelled | CancelSubscription | | Trial started | StartTrial | | Trial converted | Subscribe | | Trial cancelled | CancelTrial | | Non subscription purchase | fb_mobile_purchase | | Billing issue detected | billing_issue_detected | | Entered grace period | entered_grace_period | | Auto renew off | auto_renew_off | | Auto renew on | auto_renew_on | | Auto renew off subscription | auto_renew_off_subscription | | Auto renew on subscription | auto_renew_on_subscription | StartTrial, Subscribe ve CancelSubscription standart etkinliklerdir. <img src="/assets/shared/img/8a5df9d-CleanShot_2023-07-04_at_12.47.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Belirli etkinlikleri etkinleştirmek için istediğiniz etkinlikleri açmanız yeterlidir. Birden fazla etkinlik adı seçilmesi durumunda Adapty, seçilen tüm etkinliklerin verilerini tek bir Adapty etkinlik adı altında birleştirir. ### Uygulamanızı Facebook Ads'e bağlama \{#connect-your-app-to-facebook-ads\} Yukarıdaki adımları izlerseniz Facebook, abonelik verilerini Adapty'den otomatik olarak alır. iOS 14.5'te IDFA'ya yapılan değişikliklerin ardından, kullanıcının `facebookAnonymousId` bilgisini Facebook'tan istemenizi öneririz. Bu sayede kullanıcının IDFA'sı mevcut olmasa bile entegrasyon çalışmaya devam eder. Bu parametreyi ayarlamak için <InlineTooltip tooltip="set user attributes guide">[iOS](setting-user-attributes), [Android](android-setting-user-attributes), [React Native](react-native-setting-user-attributes), [Flutter](flutter-setting-user-attributes) ve [Unity](unity-setting-user-attributes)</InlineTooltip> kılavuzlarını takip edin. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "facebook_anonymous_id", value: AppEvents.shared.anonymousID ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier( "facebook_anonymous_id", AppEventsLogger.getAnonymousAppDeviceGUID(context) ) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers try { const anonymousId = await AppEventsLogger.getAnonymousID(); await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```text There is no official SDK for Flutter ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp anonymousID is not available in the official SDK https://github.com/facebook/facebook-sdk-for-unity/issues/676 ``` </TabItem> </Tabs> ## Etkinlik yapısı \{#event-structure\} Adapty, Graph API aracılığıyla Facebook Ads'e (Meta) etkinlik gönderir. Her etkinlik şu yapıdadır: ```json { "event": "CUSTOM_APP_EVENTS", "app_user_id": "user_12345", "advertiser_id": "00000000-0000-0000-0000-000000000000", "advertiser_tracking_enabled": 1, "application_tracking_enabled": 1, "custom_events": "[{\"_eventName\":\"Subscribe\",\"_logTime\":1709294400,\"fb_num_items\":1,\"fb_content_type\":\"in_app\",\"fb_content_id\":\"yearly.premium.6999\",\"fb_currency\":\"USD\",\"fb_order_id\":\"GPA.3383...\",\"fb_transaction_id\":\"GPA.3383...\",\"_valueToSum\":9.99}]", "extinfo": "[\"i2\",\"com.example.app\",\"1.0.0\",\"100\",\"17.0.1\",\"iPhone14,3\",\"en_US\",\"GMT+3\",\"\",0,0,0,0,0,0,\"GMT+3\"]", "anon_id": "facebook_anon_id_123" } ``` Parametreler: | Parametre | Tür | Açıklama | |:---|:---|:---| | `event` | String | Her zaman "CUSTOM_APP_EVENTS" değerini alır. | | `app_user_id` | String | Kullanıcının Customer User ID'si. | | `advertiser_id` | String | IDFA (iOS) veya Advertising ID (Android). | | `advertiser_tracking_enabled` | Integer | İzleme etkinleştirilmişse (ATT yetkili) `1`, aksi hâlde `0`. | | `application_tracking_enabled` | Integer | Her zaman `1`. | | `custom_events` | String | JSON kodlu etkinlik nesneleri dizisi (aşağıya bakın). | | `extinfo` | String | Uygulama/cihaz bilgilerini içeren JSON kodlu dize (ör. sürüm, işletim sistemi, dil ayarı). | | `anon_id` | String | Facebook Anonymous ID (mevcutsa). | `custom_events` parametresi, aşağıdakileri içeren JSON kodlu bir nesneler dizisidir: | Parametre | Tür | Açıklama | |:---|:---|:---| | `_eventName` | String | Meta Ads etkinlik adı (ör. "Subscribe"). | | `_logTime` | Long | Etkinliğin saniye cinsinden zaman damgası. | | `_valueToSum` | Float | Gelir tutarı. | | `fb_content_id` | String | Mağazadaki Ürün ID'si. | | `fb_currency` | String | Para birimi kodu (ör. "USD"). | | `fb_order_id` | String | Orijinal işlem ID'si. | | `fb_transaction_id` | String | Orijinal işlem ID'si. | | `fb_content_type` | String | Her zaman "in_app". | | `fb_num_items` | Integer | Satın alma etkinlikleri için her zaman 1. | --- # File: singular --- --- title: "Singular" description: "Singular'ı Adapty ile entegre ederek pazarlama ve abonelik verilerini analiz edin." --- [Singular](https://www.singular.net/), pazarlama kampanyalarından veri toplayıp sunan önde gelen Mobil Ölçüm Ortağı (MMP) platformlarından biridir. Bu sayede şirketler kampanya performanslarını takip edebilir. Adapty, mağazalardan gelen [abonelik etkinliklerini](events) tek bir yerden takip etmenizi sağlayan eksiksiz bir veri seti sunar. Adapty ile abonelerinizin davranışlarını kolayca görebilir, tercihlerini öğrenebilir ve bu bilgileri hedefli ve etkili bir şekilde iletişim kurmak için kullanabilirsiniz. Bu entegrasyon sayesinde Singular'da abonelik etkinliklerini takip edebilir ve kampanyalarınızın ne kadar gelir ürettiğini tam olarak analiz edebilirsiniz. Adapty, entegrasyonunuzda yapılandırılan tüm abonelik olaylarını Singular'a gönderebilir. Bu sayede söz konusu olayları Singular kontrol panelinde takip edebilirsiniz. Bu entegrasyon, reklam kampanyalarınızın etkinliğini değerlendirmek için oldukça faydalıdır. ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Singular'a Bağlama Singular entegrasyonunu kurmak için Adapty Kontrol Paneli'nde [Integrations > Singular](https://app.adapty.io/integrations/singular) bölümüne gidin, geçişi açın ve alanları doldurun. Aşağıdaki kimlik bilgileri mevcuttur: - **Singular SDK Key**: Zorunlu. Singular uygulamanızın production SDK anahtarı. - **Singular SDK Key (Sandbox)**: İsteğe bağlı. Sandbox Singular uygulamanızın SDK anahtarı. Ayarlanmazsa sandbox olayları Singular'a gönderilmez. Her iki anahtar da Singular kontrol panelinde **Developer tools -> SDK Keys -> SDK Key (**not** SDK Secret)** bölümünde bulunabilir: <img src="/assets/shared/img/4bc50d1-singular_sdk_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Kimlik bilgilerinin altında, Adapty'den Singular'a gönderebileceğiniz üç grup etkinlik bulunmaktadır. Adapty'nin sunduğu etkinliklerin tam listesini [buradan](events) inceleyebilirsiniz. <img src="/assets/shared/img/e67de0c-singular_events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin sunduğu varsayılan etkinlik adlarını kullanmanızı öneririz. Ancak etkinlik adlarını ihtiyaçlarınıza göre değiştirebilirsiniz. Adapty, abonelik etkinliklerini sunucudan sunucuya entegrasyon kullanarak Singular'a gönderir; böylece tüm abonelik etkinliklerini Singular kontrol panelinde görüntüleyebilir ve bunları edinim kampanyalarınızla ilişkilendirebilirsiniz. :::warning Entegrasyonlar yapılandırılmadan önce oluşturulan profiller, etkinliklerini Singular'a iletemiyor. ::: ### Uygulamanızı Singular'a bağlama \{#connect-your-app-to-singular\} Adapty ile Singular arasındaki entegrasyon sunucudan sunucuyadır. Bu nedenle uygulamanıza herhangi bir ek kod eklemeniz gerekmez. ## Etkinlik yapısı \{#event-structure\} Adapty, etkinlikleri Singular'a sorgu parametreleri kullanarak GET isteğiyle gönderir. Her etkinlik şu şekilde yapılandırılmıştır: ```json { "n": "subscription_renewed", "a": "singular_sdk_key_123", "p": "iOS", "i": "com.example.app", "ip": "192.168.100.1", "idfa": "00000000-0000-0000-0000-000000000000", "idfv": "00000000-0000-0000-0000-000000000000", "ve": "17.0.1", "att_authorization_status": 3, "custom_user_id": "user_12345", "utime": 1709294400, "amt": 9.99, "cur": "USD", "purchase_product_id": "yearly.premium.6999", "purchase_transaction_id": "GPA.3383...", "e": "{\"is_revenue_event\":true,\"amt\":9.99,\"cur\":\"USD\",\"purchase_product_id\":\"yearly.premium.6999\",\"purchase_transaction_id\":\"GPA.3383...\"}" } ``` Parametreler: | Parametre | Tür | Açıklama | |:---------------------------|:--------|:---------------------------------------------------------------| | `n` | String | Etkinlik adı (Adapty etkinliğinden eşlenir). | | `a` | String | Singular SDK Key'iniz. | | `p` | String | Platform ("iOS" veya "Android"). | | `i` | String | Mağaza Uygulama Kimliği (Bundle ID). | | `ip` | String | Kullanıcının IP adresi. | | `idfa` | String | **Yalnızca iOS**. Reklamverenler için Kimlik (büyük harf). | | `idfv` | String | **Yalnızca iOS**. Satıcılar için Kimlik (büyük harf). | | `aifa` | String | **Yalnızca Android**. Google Reklam Kimliği (küçük harf). | | `andi` | String | **Yalnızca Android**. Android Kimliği (küçük harf). | | `asid` | String | **Yalnızca Android**. Uygulama Set Kimliği (küçük harf). | | `ve` | String | İşletim sistemi sürümü. | | `att_authorization_status` | Integer | **Yalnızca iOS**. ATT durumu (örn. yetkili için `3`). | | `custom_user_id` | String | Kullanıcının Müşteri Kullanıcı Kimliği. | | `utime` | Long | Etkinliğin saniye cinsinden UNIX zaman damgası. | | `amt` | Float | Gelir tutarı. | | `cur` | String | Para birimi kodu (örn. "USD"). | | `purchase_product_id` | String | Mağazadaki Ürün Kimliği. | | `purchase_transaction_id` | String | Orijinal işlem kimliği. | | `e` | String | Etkinlik ayrıntılarını içeren JSON dizesi (aşağıya bakın). | `e` parametresi (özel etkinlik verisi), şunları içeren JSON kodlu bir dizedir: | Parametre | Tür | Açıklama | |:--------------------------|:--------|:--------------------------------------------| | `is_revenue_event` | Boolean | Etkinlik gelir içeriyorsa `true`. | | `amt` | Float | Gelir tutarı. | | `cur` | String | Para birimi kodu. | | `purchase_product_id` | String | Mağazadaki Ürün Kimliği. | | `purchase_transaction_id` | String | Orijinal işlem kimliği. | --- # File: tenjin --- --- title: "Tenjin entegrasyonu" description: "" --- Tenjin, uygulama geliştiricileri ve pazarlamacılar için bir mobil attribution ve analitik platformudur. Uygulama performansı ve kullanıcı davranışına ilişkin ayrıntılı bilgiler sunarak kullanıcı edinme kampanyalarını ölçmenizi ve optimize etmenizi sağlayan araçlar içerir. Şeffaf ve esnek yapısıyla Tenjin, reklam ağlarından ve uygulama mağazalarından gelen verileri bir araya getirerek ekiplerin ROI analizini yapmasına, dönüşümleri takip etmesine ve temel performans metriklerini izlemesine olanak tanır. [Abonelik etkinliklerini](events) Tenjin'e ileterek dönüşümlerin tam olarak nereden geldiğini ve hangi kampanyaların tüm kanallar, platformlar ve cihazlar genelinde en fazla değer getirdiğini görebilirsiniz. Temelde Tenjin kontrol panelleri, pazarlama kampanyaları için gelişmiş analitik sunar. Tenjin'in attribution verilerini Adapty'ye ileterek, kohort ve dönüşüm analizlerinde kullanabileceğiniz ek filtreleme kriterleriyle Adapty analitiğini zenginleştirirsiniz. Bu entegrasyon iki temel şekilde çalışır: 1. **Tenjin'den attribution verisi alma** Entegrasyon tamamlandıktan sonra Adapty, Tenjin'den attribution verisi toplar. Bu bilgilere Adapty Kontrol Paneli'ndeki kullanıcı profil sayfasından erişebilirsiniz. 2. **Tenjin'e abonelik etkinlikleri gönderme** Adapty, satın alma etkinliklerini gerçek zamanlı olarak Tenjin'e gönderir. Bu etkinlikler, reklam kampanyalarınızın etkinliğini doğrudan Tenjin'in kontrol panelinde değerlendirmenize yardımcı olur. | Entegrasyon özelliği | Açıklama | | -------------------------- | ------------------------------------------------------------ | | Zamanlama | Gerçek zamanlı | | Veri yönü | <p>İki yönlü iletim:</p><ul><li> **Adapty olayları**: Adapty sunucusundan Tenjin sunucusuna</li><li> **Tenjin attribution**: Tenjin SDK'dan Adapty sunucusuna</li></ul> | | Adapty entegrasyon noktası | <ul><li> Mobil uygulama kodunda Tenjin ve Adapty SDK'ları</li><li> Adapty sunucusu</li></ul> | ## Entegrasyonu kurma \{#set-up-integration\} ### Adapty'yi Tenjin'e bağlama \{#connect-adapty-to-tenjin\} 1. Adapty Kontrol Paneli'nde [**Integrations** -> **Tenjin**](https://app.adapty.io/integrations/tenjin) sayfasını açın. 2. Entegrasyonu etkinleştirmek için geçiş düğmesini açın. <img src="/assets/shared/img/tenjin-toggle.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. [Tenjin Dashboard](https://tenjin.com/)'a giriş yapın. 4. Gezinme menüsünde **Configuration** -> **Apps** bölümüne gidin. <img src="/assets/shared/img/tenjin-apps.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Platformunuza (iOS veya Android) ait uygulamayı seçin ve **App and SDK** sekmesine gidin. 6. **App and SDK** sekmesinde, **SDK Key** sütunundaki **Copy** butonuna tıklayın. Henüz bir SDK anahtarınız yoksa **Generate SDK Key** butonuna tıklayarak bir tane oluşturun. <img src="/assets/shared/img/tenjin-copy-sdk-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Adapty Kontrol Paneli'ne dönün ve kopyaladığınız SDK Anahtarını ilgili platform alanına yapıştırın: - iOS uygulamaları için: **iOS SDK Key** veya **iOS Sandbox SDK Key** alanına yapıştırın - Android uygulamaları için: **Android SDK Key** veya **Android Sandbox SDK Key** alanına yapıştırın :::info Tenjin'in sunucudan sunucuya entegrasyon için özel bir Sandbox modu yoktur. Hem production hem de sandbox olayları için ayrı bir Tenjin uygulaması veya aynı anahtarı kullanabilirsiniz. ::: <img src="/assets/shared/img/tenjin-keys.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. Her iki platformda da uygulamanız varsa 5-7. adımları diğer platform için tekrarlayın. 9. (isteğe bağlı) Gerekirse **How the revenue data should be sent** bölümünü düzenleyin. Ayarların ayrıntılı açıklaması için [Integration settings](configuration#integration-settings) sayfasına bakın. 10. Kurulumu tamamlamak için **Save** butonuna tıklayın. Adapty artık satın alma olaylarını Tenjin'e gönderecek ve attribution verilerini alacaktır. **Events names** bölümünden olay paylaşımını ayarlayabilirsiniz. ### Olayları ve etiketleri yapılandırma \{#configure-events-and-tags\} Tenjin yalnızca satın alma ve **Trial started** olaylarını kabul eder. **Events names** bölümünde, takip hedeflerinize uygun olarak Tenjin ile hangi olayları paylaşacağınızı seçin. <img src="/assets/shared/img/tenjin-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Uygulamanızı Tenjin'e bağlama \{#connect-your-app-to-tenjin\} Tenjin'den attribution verilerini almak ve Adapty'ye iletmek için `Adapty.updateAttribution()` SDK metodunu kullanın. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers func updateTenjinId() { guard let tenjinId = TenjinSDK.getAnalyticsInstallationId() else { return } do { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.tenjinAnalyticsInstallationId(tenjinId)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "tenjin_analytics_installation_id", value: tenjinId ) } catch { // handle the error } } func updateTenjinAttribution() { let instance = TenjinSDK.getInstance("<YOUR_TENJIN_API_TOKEN>") instance?.getAttributionInfo { info, _ in guard let info else { return } Task { do { // Adapty SDK 4.x try await Adapty.updateAttribution(info, source: .tenjin) // Adapty SDK 3.x try await Adapty.updateAttribution(info, source: "tenjin") } catch { // handle the error } } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", tenjinSdk.analyticsInstallationId) { error -> if (error != null) { // handle the error } } tenjinSdk.getAttributionInfo { attribution -> if (attribution == null) return@getAttributionInfo Adapty.updateAttribution(attribution, "tenjin") { error -> if (error != null) { // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", tenjinSdk.getAnalyticsInstallationId(), error -> { if (error != null) { // handle the error } }); tenjinSdk.getAttributionInfo(attribution -> { if (attribution == null) return; Adapty.updateAttribution(attribution, "tenjin", error -> { // handle the error }); }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers try { final tenjinId = await TenjinSDK.instance.getAnalyticsInstallationId(); if (tenjinId != null) { await Adapty().setIntegrationIdentifier( key: 'tenjin_analytics_installation_id', value: tenjinId, ); } final attribution = await TenjinSDK.instance.getAttributionInfo(); if (attribution != null) { await Adapty().updateAttribution(attribution, source: 'tenjin'); } } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; using System.Linq; BaseTenjin instance = Tenjin.getInstance("<SDK_KEY>"); var tenjinId = instance.GetAnalyticsInstallationId(); Adapty.SetIntegrationIdentifier( "tenjin_analytics_installation_id", tenjinId, (error) => { // handle the error }); instance.GetAttributionInfo((attribution) => { var dynamicAttribution = attribution.ToDictionary( kvp => kvp.Key, kvp => (dynamic)kvp.Value ); Adapty.UpdateAttribution( dynamicAttribution, "tenjin", (error) => { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... const posthog = usePostHog() // ... try { await adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", await Tenjin.getAnalyticsInstallationId()); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## Olay yapısı \{#event-structure\} Adapty, seçilen olayları [**Tenjin Integration page**](https://app.adapty.io/integrations/tenjin) üzerindeki **Events names** bölümünde yapılandırıldığı şekilde Tenjin'e gönderir. Her olay aşağıdaki yapıya sahiptir: ```json showLineNumbers title="Json" { "price": 99.0, "locale": "en-US", "country": "ME", "postcut": "false", "currency": "USD", "platform": "ios", "quantity": 1, "bundle_id": "com.adapty.adaptydemoapp", "ip_address": "127.0.0.1", "os_version": "18.1.1", "product_id": "month.premium.99", "app_version": "3.2.0", "sdk_version": "server", "device_model": "iPhone 13 Mini", "advertising_id": "00000000-0000-0000-0000-000000000000", "os_version_release": "18.1.1", "developer_device_id": "00000000-0000-0000-0000-000000000000", "analytics_installation_id": "00000000-0000-0000-0000-000000000000" } ``` Parametreler: | **Parametre** | **Tür** | **Açıklama** | | --- | --- | --- | | **price** | Float | Satın alınan ürünün para biriminin standart birimi cinsinden birim fiyatı (örneğin, USD dolar olarak raporlanır). | | **locale** | String | Cihazın yerel ayarı. Android için: `Locale.getDefault().toString()`. iOS için: `[[NSLocale currentLocale] localeIdentifier]`. | | **country** | String | ISO yerel ayar ülke kodu standardı (örneğin, Amerika Birleşik Devletleri için US). | | **postcut** | String (Boolean) | Satın almanın platform kesintisi sonrasında gönderilip gönderilmediğini belirtir. True için 1, false için 0. | | **currency** | String | ISO para birimi kodu (örneğin, ABD doları için USD). | | **platform** | String | Cihazın platformu (örneğin, ios, android, windows, amazon). | | **quantity** | Integer | Satın alınan birim sayısı. | | **bundle_id** | String | Uygulamanın paket tanımlayıcısı (örneğin, `com.example.app`). | | **ip_address** | String (IPv4) | Kullanıcının IP adresi. Ülkeyi belirlemek için kullanılır. | | **os_version** | String | Cihazın işletim sistemi sürümü. Android için: `String.valueOf(Build.VERSION.SDK_INT)`. iOS için: `[[UIDevice currentDevice] systemVersion]`. | | **product_id** | String | Satın alınan ürünün benzersiz tanımlayıcısı. | | **app_version** | Float, Decimal | Uygulamanın sürümü. Android için: `context.getPackageManager().getPackageInfo()`. iOS için: `[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]`. | | **sdk_version** | String | Kullanılan SDK sürümü; her zaman `server` olarak ayarlanır. | | **device_model** | String | Cihazın modeli. Android için: `Build.MODEL`. iOS için: `sysctl("hw.machine")`. | | **advertising_id** | UUID | Cihazın reklam kimliği. Android için zorunludur. iOS'ta boş veya sıfırlardan oluşan bir değer olabilir. | | **os_version_release** | String | İşletim sistemi sürüm yayını. Android için: `String.valueOf(Build.VERSION.RELEASE)`. iOS için: `[[UIDevice currentDevice] systemVersion]`. | | **developer_device_id** | UUID | Satıcı tanımlayıcısı (yalnızca iOS). | | **analytics_installation_id** | UUID | Analitik kurulum kimliği. Ayrıntılar için `https://docs.tenjin.com` adresindeki belgelere bakın. | --- # File: amplitude --- --- title: "Amplitude" description: "Daha iyi kullanıcı davranışı içgörüleri için Amplitude'ü Adapty ile entegre edin." --- [Amplitude](https://amplitude.com/), güçlü bir mobil analitik hizmetidir. Adapty sayesinde olayları kolayca Amplitude'e gönderebilir, kullanıcı davranışlarını inceleyebilir ve bilinçli kararlar alabilirsiniz. Adapty, mağazalardaki [abonelik olaylarını](events) tek bir yerden takip etmenizi sağlayan eksiksiz bir veri seti sunar ve bu verileri Amplitude hesabınıza gönderir. Bu sayede kullanıcı davranışlarını Amplitude'deki ödeme geçmişiyle eşleştirerek ürün kararlarınızı daha iyi temellere oturtabilirsiniz. ### Amplitude entegrasyonu nasıl kurulur \{#how-to-set-up-amplitude-integration\} Adapty'de Apple veya Stripe sandbox ortamından ya da Google test hesabından gelen **production** ve **test olayları** için ayrı flow'lar kurabilirsiniz. - Production olaylar için Amplitude kontrol panelindeki **Production** API anahtarlarını girin; iOS, Android ve Stripe için ayrı birer API anahtarı kullanın. - Test olayları için gerektiğinde **Sandbox** alanlarını kullanın. Amplitude entegrasyonunu kurmak için: 1. Adapty Kontrol Paneli'nde [**Integrations** -> **Amplitude**](https://app.adapty.io/integrations/amplitude) bölümünü açın. <img src="/assets/shared/img/3b50552-CleanShot_2023-08-15_at_16.47.102x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Amplitude integration** seçeneğini açık konuma getirerek entegrasyonu etkinleştirin. 3. Entegrasyon alanlarını doldurun: | Alan | Açıklama | | ------------------------------------------ | ------------------------------------------------------------ | | **Amplitude iOS/ Android/ Stripe API key** | iOS/ Android/ Stripe için Amplitude **API Key**'ini Adapty'ye girin. Amplitude'de **Project settings** altında bulabilirsiniz. Yardım için [Amplitude dokümanlarına](https://amplitude.com/docs/apis/authentication) bakın. Teste başlamak için **Sandbox** anahtarlarını kullanın, testler başarılı olduktan sonra **Production** anahtarlarına geçin. | <img src="/assets/shared/img/2297782-CleanShot_2023-08-15_at_16.53.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Daha fazla özelleştirme için isteğe bağlı ayarlar: | Parametre | Açıklama | | --------------------------------------- | ------------------------------------------------------------ | | **How the revenue data should be sent** | Gelir verilerini brüt olarak mı yoksa vergi ve komisyonlar düşüldükten sonra mı göndereceğinizi seçin. Ayrıntılar için [Mağaza komisyonu ve vergiler](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) bölümüne bakın. | | **Exclude historical events** | Adapty SDK kurulumundan önceki olayları dışlamak için bu seçeneği etkinleştirin; böylece veri tekrarını önlemiş olursunuz. Örneğin, kullanıcı 10 Ocak'ta abone olmuş ancak Adapty SDK'yı 6 Mart'ta kurmuşsa, Adapty yalnızca 6 Mart'tan itibaren olan olayları gönderir. | | **Send User Attributes** | Dil tercihleri gibi kullanıcıya özgü nitelikleri göndermek için bu seçeneği işaretleyin. | | **Always populate user_id** | Adapty, `device_id`'yi otomatik olarak `amplitudeDeviceId` olarak gönderir. `user_id` için bu ayar şu şekilde çalışır: <ul><li>**ON**: `amplitudeUserId` veya `customer_user_id` mevcut değilse Adapty `profile_id`'sini gönderir.</li><li>**OFF**: Her iki ID de mevcut değilse `user_id` boş bırakılır.</li></ul> | 5. Almak istediğiniz olayları seçin ve [isimlerini eşleştirin](amplitude#events-and-tags). 6. Değişikliklerinizi kaydetmek için **Save**'e tıklayın. **Save**'e tıkladıktan sonra Adapty, olayları Amplitude'e göndermeye başlayacaktır. Adapty, olayların yanı sıra [abonelik durumunu](subscription-status) ve abonelik ürün ID'sini [Amplitude kullanıcı özelliklerine](https://amplitude.com/docs/data/user-properties-and-events) gönderir. ### Olaylar ve etiketler \{#events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Amplitude'e gönderebileceğiniz üç grup olay yer almaktadır. İhtiyaç duyduklarınızı açık konuma getirmeniz yeterli. Adapty'nin sunduğu olayların tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/da67694-CleanShot_2023-08-15_at_16.52.352x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin sağladığı varsayılan olay adlarını kullanmanızı öneririz. Ancak olay adlarını ihtiyaçlarınıza göre değiştirebilirsiniz. Adapty, abonelik olaylarını sunucudan sunucuya entegrasyon aracılığıyla Amplitude'e gönderir; böylece tüm abonelik olaylarını Amplitude kontrol panelinde görüntüleyebilirsiniz. ### SDK yapılandırması \{#sdk-configuration\} `amplitude_device_id` parametresini ayarlamak için `setIntegrationIdentifier()` metodunu kullanın. Bu, entegrasyonun çalışması için zorunludur. Kullanıcı kaydınız varsa `amplitude_user_id`'yi de aktarabilirsiniz. :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="Swift" label="iOS (Swift)" default> **amplitudeDeviceId ayarlama** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "amplitude_device_id", value: Amplitude.instance().deviceId ) } catch { // handle the error } ``` **amplitudeUserId ayarlama** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "amplitude_user_id", value: "YOUR_AMPLITUDE_USER_ID" ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> **amplitudeDeviceId ayarlama** ```kotlin showLineNumbers //for Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeDeviceId = amplitude.store.deviceId // Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error -> if (error != null) { // handle the error } } ``` **amplitudeUserId ayarlama** ```kotlin showLineNumbers //for Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeUserId = amplitude.store.userId // Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="Flutter" label="Flutter (Dart)" default> **amplitudeDeviceId ayarlama** ```javascript showLineNumbers final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); try { await Adapty().setIntegrationIdentifier( key: "amplitude_device_id", value: amplitude.getDeviceId(), ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` **amplitudeUserId ayarlama** ```javascript showLineNumbers final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); try { await Adapty().setIntegrationIdentifier( key: "amplitude_user_id", value: "YOUR_AMPLITUDE_USER_ID", ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="Unity" label="Unity (C#)" default> **amplitudeDeviceId ayarlama** ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "amplitude_device_id", amplitude.getDeviceId(), (error) => { // handle the error }); ``` **amplitudeUserId ayarlama** ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "amplitude_user_id", "YOUR_AMPLITUDE_USER_ID", (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> **amplitudeDeviceId ayarlama** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` **amplitudeUserId ayarlama** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## Amplitude olay yapısı \{#amplitude-event-structure\} Adapty, olayları HTTP API v2 aracılığıyla Amplitude'e gönderir. Her olay şu şekilde yapılandırılmıştır: ```json { "api_key": "your_amplitude_api_key", "events": [ { "partner_id": "adapty", "event_type": "subscription_renewed", "time": 1709294400000, "insert_id": "123e4567-e89b-12d3-a456-426614174000", "user_id": "user_12345", "device_id": "device_12345", "platform": "iOS", "os_name": "iOS", "productId": "yearly.premium.6999", "revenue": 9.99, "event_properties": { "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383...", "currency": "USD", "environment": "Production", "store": "app_store" }, "user_properties": { "subscription_state": "subscribed", "subscription_product": "yearly.premium.6999" } } ] } ``` Parametreler: | Parametre | Tür | Açıklama | |:----------------------------|:-------|:---------------------------------------------------------------------| | `api_key` | String | Amplitude API Anahtarınız. | | `events` | Array | Olay nesnelerinin listesi (Adapty bunları tek tek gönderir). | | `events[].partner_id` | String | Her zaman "adapty". | | `events[].event_type` | String | Olay adı (Adapty olayından eşleştirilen). | | `events[].time` | Long | Olayın milisaniye cinsinden zaman damgası. | | `events[].insert_id` | String | Benzersiz olay ID'si (UUID). | | `events[].user_id` | String | Amplitude User ID veya Customer User ID. | | `events[].device_id` | String | Amplitude Device ID. | | `events[].platform` | String | Platform (örn. "iOS", "Android"). | | `events[].os_name` | String | İşletim sistemi adı. | | `events[].productId` | String | Mağazadaki Ürün ID'si. | | `events[].revenue` | Float | Gelir miktarı. | | `events[].event_properties` | Object | Ayrıntılı olay nitelikleri (mevcut tüm [olay alanlarını](webhook-event-types-and-fields#for-most-event-types) içerir). | | `events[].user_properties` | Object | Abonelik durumu gibi kullanıcı nitelikleri. | --- # File: appmetrica --- --- title: "AppMetrica" description: "Daha ayrıntılı abonelik analitiği için AppMetrica'yı Adapty ile entegre edin." --- [AppMetrica](https://appmetrica.yandex.com/about), kullanıcı davranışını izlemenize ve mobil uygulamanızın performansını gerçek zamanlı olarak analiz etmenize yardımcı olan ücretsiz bir analitik aracıdır. AppMetrica'yı Adapty ile entegre ederek abonelik metrikleriniz ve kullanıcı etkileşiminiz hakkında daha derin içgörüler elde edebilirsiniz. ## AppMetrica entegrasyonu nasıl kurulur \{#how-to-set-up-appmetrica-integration\} AppMetrica entegrasyonunu kurmak iki ana adımdan oluşur: 1. Adapty Kontrol Paneli'nde entegrasyonu yapılandırın 2. Uygulama kodunuzda entegrasyonu ayarlayın ### Kontrol paneli yapılandırması \{#dashboard-configuration\} AppMetrica entegrasyonunu kurmak için: 1. [AppMetrica uygulamalar listesini](https://appmetrica.yandex.ru/application/list) açın 2. İzlemek istediğiniz uygulamayı seçin 3. **Settings > Main** bölümüne gidin ve **Application ID** ile **Post API key** değerlerini kopyalayın <img src="/assets/shared/img/appmetrica.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty Kontrol Paneli'nde [Integrations > AppMetrica](https://app.adapty.io/integrations/appmetrica) sayfasına gidin 5. AppMetrica kimlik bilgilerinizi yapıştırın. <img src="/assets/shared/img/appmetrica_creds.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Etkinlikler ve etiketler \{#events-and-tags\} Adapty, AppMetrica'ya üç grup etkinlik göndermenize olanak tanır. Uygulamanızın performansını izlemek için ihtiyaç duyduğunuz etkinlikleri etkinleştirebilirsiniz. Mevcut etkinliklerin tam listesi için [etkinlikler belgelerimize](events) bakın. :::note AppMetrica etkinlikleri her 4 saatte bir senkronize ettiğinden, etkinliklerin kontrol panelinizde görünmesi bir süre alabilir. ::: <img src="/assets/shared/img/6ed2d88-CleanShot_2023-08-18_at_14.59.042x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::tip Tutarlılık açısından Adapty'nin varsayılan etkinlik adlarını kullanmanızı öneririz; ancak bunları mevcut analitik kurulumunuzla eşleşecek şekilde özelleştirebilirsiniz. ::: ### Gelir ayarları \{#revenue-settings\} Adapty varsayılan olarak gelir verilerini etkinliklerdeki özellikler olarak gönderir; bu veriler AppMetrica'nın Etkinlikler raporunda görünür. Bu gelir verilerinin nasıl hesaplanıp görüntüleneceğini yapılandırabilirsiniz: - **Gelir hesaplama**: Finansal raporlama ihtiyaçlarınıza uygun gelir değerlerinin nasıl hesaplanacağını seçin: - **Brüt gelir**: Herhangi bir kesinti yapılmadan önceki toplam geliri gösterir; müşterilerin ödediği tam tutarı izlemek için kullanışlıdır - **Mağaza komisyonu sonrası gelir**: App Store/Play Store ücretleri düşüldükten sonraki geliri gösterir; gerçek kazançlarınızı izlemenize yardımcı olur - **Mağaza komisyonu ve vergiler sonrası gelir**: Hem mağaza ücretleri hem de geçerli vergiler düşüldükten sonraki net geliri gösterir; kazançlarınızın en doğru görünümünü sunar - **Kullanıcının para birimini raporla**: Etkinleştirildiğinde, satışlar kullanıcının yerel para biriminde raporlanır; bu da bölgeye göre geliri analiz etmeyi kolaylaştırır. Devre dışı bırakıldığında, farklı pazarlarda tutarlı raporlama için tüm satışlar USD'ye dönüştürülür. - **Gelir etkinliklerini gönder**: Bu seçeneği etkinleştirerek gelir verilerinin yalnızca Etkinlikler raporunda değil, aynı zamanda AppMetrica'nın [Uygulama içi ve reklam geliri](https://appmetrica.yandex.com/docs/en/mobile-reports/revenue-report) raporunda da görünmesini sağlayabilirsiniz. Başka bir yerden de gelir göndermediğinizden emin olun; aksi takdirde veri tekrarına yol açabilir. - **Geçmiş etkinlikleri hariç tut**: Etkinleştirildiğinde, Adapty kullanıcının uygulamayı Adapty SDK ile yüklemesinden önce gerçekleşen etkinlikleri göndermez. Adapty'yi entegre etmeden önce zaten analitiğe etkinlik gönderiyorsanız bu, veri tekrarını önlemeye yardımcı olur. <img src="/assets/shared/img/appmetrica_revenue.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### SDK yapılandırması \{#sdk-configuration\} Uygulamanızda AppMetrica entegrasyonunu etkinleştirmek için iki tanımlayıcı ayarlamanız gerekir: 1. `appmetrica_device_id`: Temel entegrasyon için zorunludur 2. `appmetrica_profile_id`: İsteğe bağlıdır, ancak uygulamanızda kullanıcı kaydı varsa önerilir Bu değerleri ayarlamak için `setIntegrationIdentifier()` metodunu kullanın. Her platform için nasıl uygulayacağınız aşağıda açıklanmıştır: :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="Swift" label="iOS (Swift)" default> **appmetrica_device_id ayarlama** ```swift showLineNumbers AppMetrica.requestStartupIdentifiers(on: nil) { ids, error in if let error { // handle AppMetrica error return } guard let deviceIDHash = ids?[.deviceIDHashKey] as? String else { // handle AppMetrica error return } Task { do { try await Adapty.setIntegrationIdentifier( key: "appmetrica_device_id", value: deviceIDHash ) } catch { // handle the error } } } ``` **appmetrica_profile_id ayarlama** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "appmetrica_profile_id", value: "YOUR_APPMETRICA_PROFILE_ID" ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> **appmetrica_device_id ayarlama** ```kotlin showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceIdHash = result?.deviceIdHash ?: return Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash) { error -> if (error != null) { // handle the error } } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { //handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH)) ``` **appmetrica_profile_id ayarlama** ```kotlin showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceIdHash = result?.deviceIdHash ?: return Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash) { error -> if (error != null) { // handle the error } } Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error -> if (error != null) { // handle the error } } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { //handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH)) ``` </TabItem> <TabItem value="Flutter" label="Flutter (Dart)" default> **appmetrica_device_id ayarlama** ```javascript showLineNumbers final startupParams = await AppMetrica.requestStartupParams([AppMetricaStartupParams.deviceIdHashKey]); final deviceIdHash = startupParams.result?.deviceIdHash; if (deviceIdHash != null) { try { await Adapty().setIntegrationIdentifier( key: "appmetrica_device_id", value: deviceIdHash, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` **appmetrica_profile_id ayarlama** ```javascript showLineNumbers try { await Adapty().setIntegrationIdentifier( key: "appmetrica_profile_id", value: "YOUR_APPMETRICA_PROFILE_ID", ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="Unity" label="Unity (C#)" default> **appmetrica_device_id ayarlama** ```csharp showLineNumbers using AdaptySDK; using Io.AppMetrica; AppMetrica.RequestStartupParams( (result, errorReason) => { string deviceIdHash = result.DeviceIdHash; if (deviceIdHash != null) { Adapty.SetIntegrationIdentifier( "appmetrica_device_id", deviceIdHash, (error) => { // handle the error }); } }, new List<string>() { StartupParamsKey.AppMetricaDeviceIDHash } ); ``` **appmetrica_profile_id ayarlama** ```csharp showLineNumbers Adapty.SetIntegrationIdentifier( "appmetrica_profile_id", "YOUR_APPMETRICA_PROFILE_ID", (error) => { // handle the error }); ``` </TabItem> <TabItem value="RN" label="React Native (TS)" default> **appmetrica_device_id ayarlama** ```typescript showLineNumbers // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceIdHash = params?.deviceIdHash if (deviceIdHash) { try { await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_HASH_KEY]) ``` **appmetrica_profile_id ayarlama** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## AppMetrica etkinlik yapısı \{#appmetrica-event-structure\} Adapty, etkinlikleri AppMetrica'ya sorgu parametreleri olarak POST istekleri aracılığıyla gönderir. Her Adapty etkinliği için AppMetrica **iki ayrı istek** alır: 1. **Profil etkinliği** (her zaman gönderilir): Etkinlik meta verilerini içerir 2. **Gelir etkinliği** (isteğe bağlı): Adapty Kontrol Paneli'nde "Gelir etkinliklerini gönder" seçeneği etkinleştirilmişse gelir verilerini içerir ### Profil Etkinliği İsteği \{#profile-event-request\} Gönderildiği adres: `https://api.appmetrica.yandex.ru/logs/v1/import/events` Sorgu parametreli örnek URL: ``` POST https://api.appmetrica.yandex.ru/logs/v1/import/events?post_api_key=your_key&application_id=your_app_id&event_name=subscription_renewed&event_timestamp=1709294400&event_json=%7B%22vendor_product_id%22%3A%22yearly.premium%22...%7D&os_name=ios&ios_ifa=00000000-0000-0000-0000-000000000000&ios_ifv=12345678-1234-1234-1234-123456789012&profile_id=user_12345&session_type=foreground ``` Sorgu parametreleri: | Parametre | Tür | Açıklama | |:-----------------------|:-------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `post_api_key` | String | AppMetrica Post API Anahtarınız. | | `application_id` | String | AppMetrica Uygulama Kimliğiniz. | | `event_name` | String | Etkinlik adı (Adapty etkinliğinden eşlenmiş). | | `event_timestamp` | Long | Etkinliğin saniye cinsinden UNIX zaman damgası. 7 günden eski ise son 7 güne kırpılır. | | `event_json` | String | Mevcut tüm [etkinlik alanlarını](webhook-event-types-and-fields#for-most-event-types) içeren URL kodlu JSON dizesi. Yalnızca null olmayan alanlar dahil edilir. | | `os_name` | String | "ios" veya "android". | | `profile_id` | String | AppMetrica Profil Kimliği (ayarlanmışsa), aksi takdirde Müşteri Kullanıcı Kimliği (varsa). | | `appmetrica_device_id` | String | AppMetrica Cihaz Kimliği Hash'i. Yalnızca `profile_id` mevcut değilse gönderilir. | | `session_type` | String | Her zaman "foreground". | | `ios_ifa` | String | **Yalnızca iOS**. Reklamverenler için Kimlik. | | `ios_ifv` | String | **Yalnızca iOS**. Satıcılar için Kimlik. | | `google_aid` | String | **Yalnızca Android**. Google Reklam Kimliği. | ### Gelir Etkinliği İsteği (İsteğe Bağlı) \{#revenue-event-request-optional\} Gönderildiği adres: `https://api.appmetrica.yandex.ru/logs/v1/import/revenue` Bu istek yalnızca Adapty Kontrol Paneli entegrasyon ayarlarında "Gelir etkinliklerini gönder" seçeneği etkinleştirildiğinde gönderilir. Sorgu parametreli örnek URL: ``` POST https://api.appmetrica.yandex.ru/logs/v1/import/revenue?post_api_key=your_key&application_id=your_app_id&revenue_event_type=subscription_renewed&price=9.99¤cy=USD&product_id=yearly.premium&quantity=1&transaction_id=GPA.3383...&payload=%7B%22vendor_product_id%22%3A%22yearly.premium%22...%7D&os_name=ios&ios_ifa=00000000-0000-0000-0000-000000000000&profile_id=user_12345&session_type=foreground ``` Sorgu parametreleri: | Parametre | Tür | Açıklama | |:-----------------------|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `post_api_key` | String | AppMetrica Post API Anahtarınız. | | `application_id` | String | AppMetrica Uygulama Kimliğiniz. | | `revenue_event_type` | String | Gelir etkinliğinin türü (örn. "subscription_renewed", "refund", "intro_started"). Bkz. [AppMetrica etkinlik eşlemesi](#revenue-event-type-mapping). | | `price` | Float | Gelir miktarı (gelir hesaplama ayarlarınıza göre). | | `currency` | String | Para birimi kodu (örn. "USD"). | | `product_id` | String | Mağazadaki Ürün Kimliği. | | `quantity` | Integer | Her zaman 1. | | `transaction_id` | String | Mağaza İşlem Kimliği. | | `payload` | String | Etkinlik ayrıntılarını içeren URL kodlu JSON dizesi. 30 KB'ı aşarsa en kritik verileri korumak amacıyla isteğe bağlı alanlar önem sırasına göre kaldırılarak otomatik olarak kırpılır. | | `os_name` | String | "ios" veya "android". | | `profile_id` | String | AppMetrica Profil Kimliği (ayarlanmışsa), aksi takdirde Müşteri Kullanıcı Kimliği (varsa). | | `appmetrica_device_id` | String | AppMetrica Cihaz Kimliği Hash'i. Yalnızca `profile_id` mevcut değilse gönderilir. | | `session_type` | String | Her zaman "foreground". | | `ios_ifa` | String | **Yalnızca iOS**. Reklamverenler için Kimlik. | | `ios_ifv` | String | **Yalnızca iOS**. Satıcılar için Kimlik. | | `google_aid` | String | **Yalnızca Android**. Google Reklam Kimliği. | --- # File: firebase-and-google-analytics --- --- title: "Firebase ve Google Analytics" description: "Adapty abonelik olaylarını Firebase ve Google Analytics'e gönderin — Kitleler, Remote Config, Google Ads attribution ve diğer Firebase araçlarını güçlendirin." --- Adapty, abonelik olaylarını — satın almalar, yenilemeler, iadeler, deneme başlangıçları — Firebase ve Google Analytics'e iletebilir; böylece tek bir entegrasyon her ikisine de veri sağlar. :::warning Hem bir Firebase projesine hem de bağlı bir Google Analytics özelliğine ihtiyacınız var — yalnızca birini kullansanız bile. Firebase ve Google Analytics, iki farklı konsolda gösterilen aynı veridir. ::: Satın alma ve iade etkinlikleri; gelir, para birimi ve ürün ayrıntılarıyla birlikte gelir. Aynı veriler hem Firebase'in mobil araçlarını (Audiences, Remote Config vb.) hem de Google Analytics'teki raporlamayı besler. Bu bir analytics entegrasyonudur, Google Ads attribution aracı değildir — bkz. [Sınırlamalar](#limitations). ## Bu entegrasyonla neler yapabilirsiniz \{#what-you-can-do-with-this-integration\} Adapty, kullanıcıları `subscription_state` (`subscribed`, `active_trial`, `never_subscribed` vb.) değerine göre gruplandırır ve abonelik yaşam döngüsü olaylarını Firebase ile Google Analytics'e iletir. - **Kitleler**: Firebase ve Google Analytics'te abone kitleleri oluşturun — Google Ads yeniden hedefleme, FCM kampanyaları, benzer kitle modellemesi. - **Google Ads dönüşümleri** *(Google Analytics)*: `purchase` ve `refund` olaylarını Google Ads dönüşüm hedefi olarak kullanın. - **Firebase Remote Config**: Abonelik durumuna göre koşul tanımlayarak kullanım limitlerini, metinleri veya özellik bayraklarını uygulama güncellemesi gerektirmeden değiştirin. (Flow/paywall içeriğini yapılandıran [Adapty Remote Config](customize-paywall-with-remote-config) ile karıştırmayın.) - **Cloud Messaging**: Uygulama kapalıyken pasif abonelere anlık bildirim gönderin. - **Cihazlar arası takip** *(Google Analytics)*: Adapty, Google Analytics'e `customer_user_id` gönderir; böylece Google Ads aynı kişiyi farklı cihazlarda takip edebilir. - **Dönüşüm hunileri** *(Google Analytics)*: Kullanıcıların dönüşüm gerçekleştirmeden veya uygulamayı bırakmadan önce neler yaptığını görün. - **Tahminler**: Satın alma geçmişini kullanarak kayıp ve harcama tahminleri yapın. - **A/B Testi**: Abone kohortlarında uygulama özelliklerini test edin — örneğin deneme kullanıcılarına yeni bir navigasyon düzeni sunarak oturum uzunluğunu ölçün. (Paywall varyantları için [Adapty A/B Testleri](ab-tests)'ni kullanın.) ## Entegrasyon nasıl çalışır \{#how-the-integration-works\} 1. Bir kullanıcı uygulamanızı ilk kez açtığında, Firebase SDK kurulum için benzersiz bir tanımlayıcı oluşturur — **Firebase App Instance ID**. Firebase ve Google Analytics, her etkinlikten sorumlu kurulumu tanımlamak için bu kimliği kullanır. 2. Uygulamanız, Firebase App Instance ID'yi Adapty'nin SDK'sına iletir. Adapty, kullanıcının profilini bu Firebase kurulumuna bağlar. 3. Kullanıcı bir satın alma işlemi gerçekleştirdiğinde, Adapty'nin sunucuları etkinliği Firebase App Instance ID ile birlikte Firebase'e iletir. Veriler, uygulama dışında sunucular arasında aktarılır. 4. Firebase, satın almayı ilgili kurulumla eşleştirir; böylece satın almaları kullanıcının uygulamada yaptığı diğer her şeyle birlikte görebilirsiniz. :::note Firebase App Instance ID cihaza özgüdür. Aynı Adapty kullanıcısı uygulamayı başka bir cihazda açtığında, yeni Firebase ID öncekinin üzerine yazar. Cihazlar arasında kullanıcı kimliğini korumak için [customer user ID](identifying-users) kullanın. ::: ### Stripe satın almaları \{#stripe-purchases\} Bir Stripe satın alımının Firebase'e ulaşması için alıcının önce mobil uygulamanızı açmış olması gerekir. Firebase App Instance ID, Stripe satın alımı gerçekleşmeden **önce** ayarlanmış olmalıdır. App Store ve Play Store satın alımlarında bu işlem otomatik olarak gerçekleşir. Bu satın alımlar, [`setIntegrationIdentifier`](#configure-your-app-code) çağrısıyla birlikte doğrudan mobil uygulamanızın içinden başlatılır. Bu nedenle satın alım gerçekleştiğinde Firebase ID zaten mevcut olur. Stripe satın almaları uygulama dışında, sunucunuzda gerçekleşir. Mobil uygulamanız başlatılırken — herhangi bir Stripe satın alımı gerçekleşmeden önce — `setIntegrationIdentifier` çağrısı yapmalıdır. Aksi takdirde Adapty'nin ekleyeceği bir ID olmaz ve Stripe satın alımı hiçbir zaman Firebase'e ulaşmaz. ### Sınırlamalar \{#limitations\} - **Google Ads attribution aracı değildir.** Bu entegrasyon, Adapty event'lerini analitik amacıyla Firebase ve Google Analytics'e gönderir. Uygulama yüklemelerini Google Ads kampanyalarına (UAC / Universal App Campaigns) bağlamaz veya ücretli trafiği organik trafikten ayırt etmez. Yükleme attribution'ı için Adapty'nin yerleşik [Adapty Attribution](adapty-user-acquisition) özelliğini kullanın. - **Geçmişe dönük veri aktarımı yapılmaz.** Adapty, entegrasyonu etkinleştirdiğiniz andan itibaren event'leri iletir — geçmişteki satın almalar, yenilemeler ve iade işlemleri Firebase'e ulaşmaz. (Geçmiş veriler Adapty'nin [S3](s3-exports) / [GCS](google-cloud-storage) dışa aktarmalarında bulunur, ancak bu verileri Firebase'e aktarmak bu entegrasyonun kapsamında değildir.) - **Yalnızca web üzerinden satın alanlar Firebase'e ulaşmaz.** Adapty, satın almaları Firebase'e mobil uygulamanızın belirlediği Firebase App Instance ID üzerinden iletir. Uygulamayı hiç yüklememiş alıcıların ID'si olmadığından satın almaları Firebase'e ulaşmaz. Ayrıntılar için yukarıdaki [Stripe satın almaları](#stripe-purchases) bölümüne bakın; web takibi için [FunnelFox'un Firebase entegrasyonunu](https://funnelfox.com/docs/integrations/subscription-management/adapty) veya Google Analytics web veri akışını değerlendirin. - **Paddle satın almaları dahil değildir.** Bu entegrasyon şu an için Paddle'ı desteklememektedir. Paddle satın almaları Adapty Analytics'te kalır ve bu yol üzerinden Firebase'e ulaşmaz. - **Stripe satın almaları, Stripe'a özgü kısıtlamaları devralır.** Bkz. [Stripe entegrasyon kısıtlamaları](stripe#current-limitations). ## Kurulum talimatları \{#setup-instructions\} ### Firebase'i Yapılandırma \{#configure-firebase\} 1. [Firebase Console](https://console.firebase.google.com/) adresini açın ve bir proje seçin ya da oluşturun. Üretim analizlerini sandbox olaylarından temiz tutmak için geliştirme build'leri için ayrı bir Firebase projesi kullanın. 2. Projeyi bir Google Analytics mülküyle ilişkilendirin. Firebase, proje oluşturma sırasında bunu size sorar; ya da daha sonra **Project settings** > **Integrations** > **Google Analytics** yolunu izleyerek ekleyebilirsiniz. 3. **Project settings** > **General** > **Your apps** bölümünde, yayınladığınız her platform (iOS / Android / Web) için ayrı bir giriş ekleyin. Stripe için bir Web uygulaması girişi ekleyin — yerel bir Stripe uygulama türü yoktur. Her giriş, benzersiz bir **Firebase App ID** ve Google Analytics'te karşılık gelen bir veri akışı oluşturur. Kurulum sırasında bu ID'yi Adapty'nin Firebase entegrasyon ayarlarına yapıştıracaksınız. ### Adapty'yi Yapılandırın \{#configure-adapty\} 1. Adapty Kontrol Paneli'nde [**Integrations** > **Firebase**](https://app.adapty.io/integrations/firebase) sayfasını açın. 2. **Firebase integration** geçiş düğmesini etkinleştirin. 3. Uygulama yayınladığınız her platform için kimlik bilgilerini girin. Adapty, her platform için hem bir **Firebase App ID** hem de bir **Google Analytics secret** gerektirir — bu değerler iOS, Android ve Stripe arasında farklılık gösterir. | Adapty Kontrol Paneli | Google Analytics | Nerede bulunur | | --- | --- | --- | | **Firebase App ID** | **App ID** | Firebase Console > **Project settings** > **General** > **Your apps** | | **Google Analytics secret** | **Measurement Protocol API secret** | Google Analytics > **Admin** > **Data streams** > **Measurement Protocol API secrets** > **Create** | 4. Adapty'nin gelir ve kullanıcı verilerini nasıl ileteceğini yapılandırın. Dört kontrol, kontrol panelinde tek bir satırda yer alır: - **Revenue definition** açılır menüsü: Brüt gelir, Mağaza komisyonu sonrası gelir veya [Mağaza komisyonu ve vergiler sonrası gelir](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue). - **Send user properties** geçişi: Açık olduğunda, olaylar `subscription_state` ve `subscription_product_id` içerir. Bunları raporlarda veya kitlelerde kullanmak için bkz. [Abonelik verilerini raporlarda kullanma](#use-subscription-data-in-reports-and-audiences). - **Report user's currency** geçişi: Açık olduğunda, Adapty her işlemin yerel para birimini Google Analytics'e iletmeden önce hesabınızın raporlama para birimine dönüştürür. - **Send trial price** geçişi: Deneme başlangıçları değerlidir — ödeme yapan kullanıcıların büyük çoğunluğu genellikle bir denemeyle başlar. Ancak Google Ads'in teklif optimizasyonu yalnızca geliri olan olayları hedeflenmeye değer olarak kabul eder. Bunu açarak her denemeye bir yer tutucu fiyat atayabilirsiniz; böylece Google bu denemeleri dönüşüm olarak görür ve reklam harcamasını deneme başlatıcıları kazanmaya yönelik optimize eder. Açık olduğunda **Trial price percentage** alanı görünür. Bu alana, Google'ın her denemeyi tam abonelik fiyatının yüzde kaçı olarak değerlendireceğini girin; örneğin `50%` ayarlarsanız deneme süresince abonelik fiyatının yarısı raporlanır. 5. Adapty olaylarını Firebase/Google Analytics olay adlarıyla eşleştirin. Adapty, **iOS** ve **Android** için ayrı olay haritaları sunar; böylece her platform için farklı adlar kullanabilirsiniz. **Stripe satın almaları iOS olay haritasını kullanır** — ayrı bir Stripe haritası yoktur. Google Analytics, katı Measurement Protocol sınırları uygular — 40 karakterlik event adları, 24 karakterlik kullanıcı özelliği adları ve 36 karakterlik değerler. Google Analytics, bu sınırları aşan özel eventleri sessizce atar. :::warning Bazı eventler, Firebase ve Google Analytics'te rezerve edilmiş e-ticaret söz dizimini kullanır — `purchase` ve `refund`. Google Ads dönüşüm içe aktarma, Google Analytics gelir raporları ve tahmine dayalı kitleler bu tam string değerlerine bağlıdır. Bu özelliklere ihtiyaç duymuyorsanız varsayılanları geçersiz kılın. ::: 6. **Save** düğmesine tıklayın. Adapty, birkaç dakika içinde olayları Firebase'e iletmeye başlar. ### Uygulama kodunuzu yapılandırın \{#configure-your-app-code\} :::tip Uygulamanızın <InlineTooltip tooltip="Firebase SDK">[iOS](https://firebase.google.com/docs/ios/setup), [Android](https://firebase.google.com/docs/android/setup), [Flutter](https://firebase.google.com/docs/flutter/setup), [Unity](https://firebase.google.com/docs/unity/setup), [React Native](https://rnfirebase.io/) ve [Capacitor](https://github.com/capawesome-team/capacitor-firebase)</InlineTooltip> içerdiğinden emin olun. ::: Adapty, her etkinlikle birlikte **Firebase App Instance ID**'yi eklemek zorundadır — aksi takdirde hiçbir şey Firebase'e ulaşmaz (`MISSING_INTEGRATION_ID`). `FirebaseApp.configure()` ve `Adapty.activate()` çağrılarından sonra, Firebase SDK'dan App Instance ID'yi isteyin. `setIntegrationIdentifier` aracılığıyla Adapty'ye iletin. Bunu her uygulama başlatmada, herhangi bir satın alma akışından önce bir kez çalıştırın. :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> <Tabs groupId="sdk-version" queryString> <TabItem value="v4" label="Adapty SDK v4+"> ```swift showLineNumbers FirebaseApp.configure() if let appInstanceId = Analytics.appInstanceID() { do { try await Adapty.setIntegrationIdentifier(.firebaseAppInstanceId(appInstanceId)) } catch { // handle the error } } ``` </TabItem> <TabItem value="v3" label="Adapty SDK v3" default> ```swift showLineNumbers FirebaseApp.configure() if let appInstanceId = Analytics.appInstanceID() { do { try await Adapty.setIntegrationIdentifier( key: "firebase_app_instance_id", value: appInstanceId ) } catch { // handle the error } } ``` </TabItem> </Tabs> </TabItem> <TabItem value="kotlin" label="Android (Kotlin)"> ```kotlin showLineNumbers // after Adapty.activate() FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId -> Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error -> if (error != null) { // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)"> ```java showLineNumbers // after Adapty.activate() FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> { if (error != null) { // handle the error } }); }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)"> ```dart showLineNumbers final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; if (appInstanceId != null) { try { await Adapty().setIntegrationIdentifier( key: "firebase_app_instance_id", value: appInstanceId, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` </TabItem> <TabItem value="unity" label="Unity (C#)"> ```csharp showLineNumbers using AdaptySDK; using Firebase.Analytics; FirebaseAnalytics .GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread((task) => { if (!task.IsCompletedSuccessfully) { // handle the error return; } Adapty.SetIntegrationIdentifier( "firebase_app_instance_id", task.Result, (error) => { // handle the error } ); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)"> ```typescript showLineNumbers try { const appInstanceId = await analytics().getAppInstanceId(); if (appInstanceId) { await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ### Entegrasyonu doğrulama \{#verify-the-integration\} Olayların akıp akmadığını doğrulamanın en hızlı yolu Firebase DebugView'dır: 1. Bir test cihazında, [Firebase hata ayıklama modu etkin](https://firebase.google.com/docs/analytics/debugview#enable_debug_mode) olarak uygulamanızı çalıştırın. 2. Adapty Kontrol Paneli'nde etkinleştirdiğiniz bir sandbox satın alımını veya herhangi bir olayı tetikleyin. 3. Firebase Console > **Analytics** > **DebugView** yolunu izleyin. Olaylar, tüm parametreleriyle birlikte saniyeler içinde görünür. Standart raporlar — Realtime, Reports, kitleler — rapora bağlı olarak birkaç dakika ile 24 saat içinde dolmaya başlar. Gerçek zamanlı doğrulama yapabileceğiniz tek yer DebugView'dır. ## Raporlarda ve kitlelerde abonelik verilerini kullanma \{#use-subscription-data-in-reports-and-audiences\} Adapty Kontrol Paneli'nde **Send user properties** seçeneğini etkinleştirin ([Adapty'yi Yapılandırma](#configure-adapty), 4. adım). Bu olmadan Adapty, `subscription_state` veya `subscription_product_id` verilerini iletmez — ve bu bölümün geri kalanı hiçbir şey yapmaz. Varsayılan olarak, Firebase ve Google Analytics kullanıcı özelliklerini göstermez. Her birini özel boyut olarak kaydedin. Bu sayede `subscription_state` ve `subscription_product_id` raporlarda, Explorations'ta ve kitlelerde kullanılabilir hale gelir. Boyutları Google Analytics Admin'de yapılandırın. Ardından hem Firebase'de hem de Google Analytics'te sorgulayabilirsiniz — ikisi aynı arka ucu paylaşır. Ödeme yapan kullanıcıların Google Ads kitlelerini oluşturmak veya tahmin modellerini beslemek için kullanışlıdır. Kurulumu tamamladığınızda, Adapty bu özellikleri sonraki etkinlikler için dolduracaktır. Mevcut etkinlikler güncellenmeyecektir. 1. Google Analytics'te **Admin** > **Custom definitions** bölümünü açın. 2. **Create custom dimensions** seçeneğine tıklayın. 3. Her özellik için şunları ayarlayın: - **Dimension name**: İnsan tarafından okunabilir herhangi bir ad, örneğin "Subscription state". - **Scope**: **User**. - **User property**: `subscription_state` veya `subscription_product_id`. Ad tam olarak eşleşmelidir — Google Analytics büyük/küçük harfe duyarlıdır. ## Sorun giderme \{#troubleshooting\} ### Firebase'de etkinlikler görünmüyor \{#events-dont-appear-in-firebase\} - Firebase App Instance ID'nin ilk satın alma yapılmadan **önce** ayarlandığını doğrulayın. Firebase ID'si olmayan etkinlikler Firebase'e ulaşmaz ve hata üretir. - Firebase Console'da bağlı olan Google Analytics özelliğinin veri akışıyla eşleştiğini doğrulayın. - Adapty'deki kimlik bilgilerinin (ID + gizli anahtar) platforma uyduğunu doğrulayın. ### `access_level_updated` Event Feed'de başarısız olarak görünüyor \{#access_level_updated-shows-as-failed-in-the-event-feed\} `access_level_updated` **yalnızca webhook'a özel bir event**'tir. Adapty bunu Firebase'e iletmeye hiçbir zaman çalışmaz — ancak Event Feed yine de bunu başarısız bir teslimat olarak listeler. Bu satırı görmezden gelin. Entegrasyonunuz sorunsuz çalışıyor. Bu event'i kullanmak için [webhook entegrasyonunu](webhook) yapılandırın. ### Sandbox olayları üretim verilerini kirletiyor \{#sandbox-events-pollute-production-data\} Adapty, sandbox ve üretim işlemlerini aynı Firebase projesine iletir. [Firebase'i Yapılandırma](#configure-firebase) bölümüne bakın — geliştirme derlemeleri için ayrı bir Firebase projesi kullanmak bu sorunu tamamen ortadan kaldırır. ### Firebase, StoreKit 2 uygulamalarında geliri eksik sayıyor \{#firebase-undercounts-revenue-for-storekit-2-apps\} Firebase, her StoreKit 1 satın alımı için otomatik olarak bir `in_app_purchase` etkinliği kaydeder — bunu için herhangi bir kod gerekmez. StoreKit 2 ise farklı bir API kullanır. Firebase bu işlemleri hiç görmez. Sonuç: Ayrı bir gelir pipeline'ı olmayan SK2 ağırlıklı uygulamalar, Firebase'de, Google Analytics'te ve tüm aşağı yöndeki Google Ads kampanyalarında gerçek değerin yarısını ya da daha azını raporlar. Teklif optimizasyonu yanlış sayıya göre çalışır. Gelir raporları resmin yalnızca yarısını gösterir. Düzeltme: `firebase_app_instance_id` değerini Adapty'ye iletin (bkz. [Uygulama kodunuzu yapılandırın](#configure-your-app-code)). Adapty, her satın almayı Measurement Protocol aracılığıyla iletir — gelir, para birimi ve ürün bilgisiyle birlikte. ### Adapty Analytics ve Firebase rakamları neden farklı \{#adapty-analytics-and-firebase-numbers-diverge\} - **StoreKit 2**: Açık ara en büyük neden. Bkz. [Firebase, StoreKit 2 uygulamaları için geliri eksik sayıyor](#firebase-undercounts-revenue-for-storekit-2-apps). - **SDK benimsenmesi**: Firebase yalnızca Firebase App Instance ID gönderen kullanıcıların etkinliklerini sayar. Eski uygulama sürümleri bu çağrıyı yapmaz. Adapty bu kullanıcıları yine de sayar; Firebase saymaz. - **Sandbox etkinlikleri**: Adapty, sandbox işlemlerini de Firebase'e iletir. Bunları üretim verilerinden ayırmak için geliştirme derlemeleri için ayrı bir Firebase projesi kullanın. - **Örnekleme**: Google Analytics Explorations büyük veri kümelerini örnekler. Örneklenmemiş sayılar için Gerçek Zamanlı görünümü veya standart raporları kontrol edin. ### Özel etkinlik adları Google Analytics tarafından reddediliyor \{#custom-event-names-are-rejected-by-google-analytics\} Google Analytics, etkinlik adlarını 40 karakterle, yalnızca alfanümerik ve alt çizgi içerecek şekilde ve bir harfle başlayacak biçimde sınırlandırır. Bu kurallara uymayan özel Adapty etkinliklerini kontrol panelinde yeniden adlandırın. --- # File: mixpanel --- --- title: "Mixpanel" description: "Güçlü abonelik analitiği için Mixpanel'i Adapty ile bağlayın." --- [Mixpanel](https://mixpanel.com/home/), güçlü bir ürün analitik hizmetidir. Olay tabanlı takip çözümü, ürün ekiplerine farklı platformlarda kullanıcı kazanımı, dönüşüm ve elde tutma stratejilerine dair değerli içgörüler sunar. Bu entegrasyon, tüm Adapty etkinliklerini Mixpanel'e aktarmanızı sağlar. Böylece abonelik işiniz ve müşteri davranışları hakkında çok daha kapsamlı bilgiler edinirsiniz. Adapty, mağazalardan gelen [abonelik etkinliklerini](events) tek bir yerden takip etmenizi sağlayan eksiksiz bir veri seti sunar. Adapty sayesinde abonelerinizin davranışlarını kolayca görebilir, ne istediklerini öğrenebilir ve bu bilgileri kullanarak onlarla hedefli ve etkili bir şekilde iletişim kurabilirsiniz. ## Mixpanel entegrasyonunu nasıl kurarsınız \{#how-to-set-up-mixpanel-integration\} 1. Adapty Kontrol Paneli'nde [Integrations -> Mixpanel](https://app.adapty.io/integrations/mixpanel) sayfasını açın. 2. Geçiş düğmesini etkinleştirin ve **Mixpanel Token** bilginizi girin. Tüm platformlar için tek bir token belirleyebilir ya da yalnızca belirli platformlardan veri almak istiyorsanız bunu spesifik platformlarla sınırlayabilirsiniz. 3. **Mixpanel Data Residency** alanını Mixpanel projenizle eşleşecek şekilde ayarlayın. Bu alan zorunludur ve varsayılan değeri **US**'dir. `api.mixpanel.com` uç noktası için **US**, `api-eu.mixpanel.com` için **Europe** seçeneğini seçin. :::warning Mixpanel projeniz AB veri merkezini kullanıyorsa, **Mixpanel Data Residency** değerini **Europe** olarak ayarlamanız gerekir. Mixpanel, AB projelerinden ABD uç noktasına gönderilen etkinlikleri reddeder. ::: <img src="/assets/shared/img/mixpanel.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Mixpanel Token'ınızı bulma \{#finding-your-mixpanel-token\} **Mixpanel Token**'ınızı almak için: 1. [Mixpanel Dashboard](https://mixpanel.com/settings/project/)'unuza giriş yapın. 2. **Settings** bölümünü açın ve **Organization Settings** seçeneğini tıklayın. <img src="/assets/shared/img/mixpanel-settings.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Sol kenar çubuğundan **Projects** bölümüne gidin ve projenizi seçin. <img src="/assets/shared/img/mixpanel-project-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Entegrasyon nasıl çalışır \{#how-the-integration-works\} Adapty, kullanıcı kimliği ve gelir gibi ilgili olay özelliklerini otomatik olarak [Mixpanel'e özgü özelliklere](https://docs.mixpanel.com/docs/data-structure/user-profiles) eşler. Bu sayede abonelikle ilgili olaylar doğru bir şekilde takip edilir ve raporlanır. Bunun yanı sıra Adapty, kullanıcı başına gelir verilerini biriktirir ve `subscription state` ile `subscription product ID` dahil olmak üzere [Kullanıcı Profil Özelliklerini](https://docs.mixpanel.com/docs/data-structure/user-profiles) günceller. Bir olay alındığında Mixpanel, ilgili alanları gerçek zamanlı olarak günceller. ## Olaylar ve etiketler \{#events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Mixpanel'e gönderebileceğiniz üç grup olay bulunur. İhtiyacınız olanları açmanız yeterli. Adapty'nin sunduğu olayların tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/mixpanel-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin sağladığı varsayılan olay adlarını kullanmanızı öneririz. Ancak ihtiyacınıza göre olay adlarını değiştirebilirsiniz. ## SDK yapılandırması \{#sdk-configuration\} `mixpanelUserId` ayarlamak için `.setIntegrationIdentifier()` metodunu kullanın. Bu değer ayarlanmazsa Adapty, kullanıcı kimliğinizi (`customerUserId`) ya da bu değer null ise Adapty ID'sini kullanır. Uygulamanızdan Mixpanel'e veri göndermek için kullandığınız kullanıcı kimliğinin Adapty'e gönderdiğinizle aynı olduğundan emin olun. :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "mixpanel_user_id", value: Mixpanel.mainInstance().distinctId ) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(mixpanelUserId: Mixpanel.mainInstance().distinctId) Adapty.updateProfile(params: builder.build()) ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { await Adapty().setIntegrationIdentifier( key: "mixpanel_user_id", value: distinctId, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; var distinctId = Mixpanel.DistinctId; if (distinctId != null) { Adapty.SetIntegrationIdentifier( "mixpanel_user_id", distinctId, (error) => { // handle the error }); } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // If you already have a shared Mixpanel instance in your app, use that instance instead. const trackAutomaticEvents = true; const mixpanel = new Mixpanel('YOUR_PROJECT_TOKEN', trackAutomaticEvents); await mixpanel.init(); // This is Mixpanel's current distinct_id (auto-generated, or set via mixpanel.identify(...)) const mixpanelUserId = await mixpanel.getDistinctId(); try { await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## Mixpanel olay yapısı \{#mixpanel-event-structure\} Adapty, olayları Mixpanel'e `track` metodu aracılığıyla gönderir. Olay özellikleri şu şekilde yapılandırılmıştır: ```json { "event": "subscription_renewed", "properties": { "ip": 0, "time": 1709294400, "$insert_id": "123e4567-e89b-12d3-a456-426614174000", "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383...", "currency": "USD", "environment": "Production", "store": "app_store", "purchase_date": "2024-03-01T12:00:00.000000+0000" } } ``` Parametreler: | Parametre | Tür | Açıklama | |:-------------------------------------|:--------|:----------------------------------------------------------------| | `event` | String | Olay adı (Adapty olayından eşlenir). | | `properties` | Object | Olay özellikleri. | | `properties.ip` | Integer | IP adresi (sunucudan sunucuya iletimde 0 olarak gönderilir). | | `properties.time` | Long | Olayın saniye cinsinden UNIX zaman damgası. | | `properties.$insert_id` | String | Tekilleştirme için benzersiz olay kimliği (UUID). | | `properties.vendor_product_id` | String | Mağazadaki Ürün Kimliği. | | `properties.original_transaction_id` | String | Orijinal işlem kimliği. | | `properties.currency` | String | Para birimi kodu. | | `properties.store` | String | Mağaza adı (örn. "app_store"). | | `properties.environment` | String | Ortam ("Sandbox" veya "Production"). | ### Kullanıcı profili güncellemeleri \{#user-profile-updates\} Adapty aynı zamanda `people_set` aracılığıyla Mixpanel Kullanıcı Profilini şu özelliklerle günceller: | Parametre | Tür | Açıklama | |:--------------------------|:-------|:---------------------------------------------------------------| | `subscription_state` | String | Mevcut abonelik durumu (örn. "subscribed"). | | `subscription_product_id` | String | Aktif abonelik ürününün kimliği. | --- # File: posthog --- --- title: "PostHog" description: "" --- PostHog, kullanıcı davranışını takip etmek, ürün kullanımını görselleştirmek ve retention analizi yapmak için araçlar sunan bir analitik platformdur. Etkinlik takibi, kullanıcı akışları ve özellik bayrakları gibi özellikleriyle ürününüzü daha iyi anlamanıza ve geliştirmenize yardımcı olmak için tasarlanmıştır. PostHog'u Adapty ile entegre etmek; deneme başlangıçları, yenilemeler ve iptaller gibi abonelikle ilgili olayları sorunsuz biçimde izlemenizi sağlar. Bu olayları PostHog'a göndererek abonelik değişikliklerinin kullanıcı davranışını nasıl etkilediğini analiz edebilir, paywall performansını değerlendirebilir ve mevcut analitik iş akışınız içinde monetizasyon stratejilerinize dair daha derin içgörüler elde edebilirsiniz. ## Entegrasyon Özellikleri \{#integration-characteristics\} | Entegrasyon özelliği | Açıklama | | -------------------------- | ------------------------------------------------------------ | | Zamanlama | Gerçek zamanlı; etkinlikler PostHog kontrol panelinde hemen görünmeyebilir. | | Veri yönü | Adapty etkinlikleri, Adapty sunucusundan PostHog sunucusuna gönderilir. | | Adapty entegrasyon noktası | <ul><li> Mobil uygulama kodunda PostHog ve Adapty SDK'ları</li><li> Adapty sunucusu</li></ul> | ## PostHog etkinlik yapısı \{#posthog-event-structure\} Adapty, seçilen etkinlikleri [PostHog Entegrasyon sayfasındaki](https://app.adapty.io/integrations/posthog) **Events names** bölümünde yapılandırıldığı şekilde PostHog'a gönderir. Her etkinlik şu yapıya sahiptir: ```json showLineNumbers { "distinct_id": "john.doe@example.com", "timestamp": "2025-01-08T11:06:12+00:00", "event": "subscription_started", "properties": { "$set": { "email": "user@example.com", "first_name": "John", "last_name": "Doe", "birthday": "1990-01-01", "gender": "male", "os": "iOS" }, "timezone": "America/New_York", "ip_address": "10.168.1.1", "*": "{{other_event_properties}}" } } ``` Parametreler: | **Parametre** | **Tür** | **Açıklama** | | --------------- | -------------------- | ------------------------------------------------------------ | | **distinct_id** | String | Kullanıcı için benzersiz tanımlayıcı (ör. `profile.posthog_distinct_user_id`, `customer_user_id` veya `profile_id`). | | **timestamp** | ISO 8601 tarih ve saat | Etkinliğin tarihi ve saati. | | **event** | String | [PostHog yapılandırmasının](https://app.adapty.io/integrations/posthog) Events names bölümünde tanımladığınız etkinlik adı. | | **properties** | Object | [properties.$set](posthog#propertiesset-parameters) parametrelerini ve tüm [etkinliğe özgü özellikleri](messaging#event-properties) içerir. Her özellik isteğe bağlıdır; eksik olması durumunda PostHog'a gönderilmez. | ### properties.$set parametreleri \{#propertiesset-parameters\} Her `properties.$set` nesne parametresi isteğe bağlıdır; eksik olması durumunda PostHog'a gönderilmez. | **Parametre** | **Tür** | **Açıklama** | | --------------- | -------------------- | ------------------------------------------------------------ | | **email** | String | Kullanıcının e-posta adresi. | | **first_name** | String | Kullanıcının adı. | | **last_name** | String | Kullanıcının soyadı. | | **birthday** | String (Date) | Kullanıcının doğum tarihi. | | **gender** | String | Kullanıcının cinsiyeti. | | **os** | String | Kullanıcının cihazının işletim sistemi. | ## PostHog entegrasyonunu kurma \{#setting-up-posthog-integration\} 1. Adapty Kontrol Paneli'nde [Integrations -> PostHog](https://app.adapty.io/integrations/posthog) sayfasını açın ve geçişi etkinleştirin. <img src="/assets/shared/img/posthog-on.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. [PostHog Kontrol Paneli](https://posthog.com/)'ne giriş yapın. 3. **Settings -> Project** bölümüne gidin. 4. **Project** penceresinde **Project ID** bölümüne kadar aşağı kaydırın ve **Project API key** değerini kopyalayın. 5. API anahtarını Adapty Kontrol Paneli'ndeki **Project API key** alanına yapıştırın. PostHog, sunucudan sunucuya entegrasyon için özel bir Sandbox modu sunmaz. 6. **PostHog Deployment** seçeneğinizi belirleyin: | Seçenek | Açıklama | | ------ | ------------------------------------------------------------ | | us/eu | Varsayılan PostHog barındırmalı dağıtımlar. | | Custom | Kendi barındırdığınız örnekler için. Örnek URL'nizi **PostHog Instance URL** alanına girin. | 7. (isteğe bağlı) Kendi barındırdığınız bir PostHog dağıtımı kullanıyorsanız, dağıtımınızın adresini **PostHog Instance URL** alanına girin. 8. (isteğe bağlı) **Reporting Proceeds**, **Exclude Historical Events**, **Report User's Currency** ve **Send Trial Price** gibi ayarları düzenleyin. Bu seçenekler hakkında ayrıntılı bilgi için [Integration settings](configuration#integration-settings) bölümüne bakın. 9. (isteğe bağlı) **Events names** bölümünde PostHog'a hangi etkinliklerin gönderileceğini özelleştirebilirsiniz. İstemediğiniz etkinlikleri devre dışı bırakın veya gerektiğinde yeniden adlandırın. 10. Kurulumu tamamlamak için **Save**'e tıklayın. ## SDK yapılandırması \{#sdk-configuration\} PostHog'dan attribution verisi alabilmek için `distinctId` değerini aşağıda gösterildiği gibi Adapty'e iletin: :::note Üçüncü taraf SDK'lar kullanıcı kimliklerini asenkron olarak oluşturur. `Adapty.activate()` çalıştığında bu kimlik henüz hazır olmayabilir. **Customer User ID**'niz bu SDK'lardan birinden geliyorsa, `Adapty.activate()` fonksiyonunu kimlik olmadan çağırın. Kimlik hazır olduğunda önce `setIntegrationIdentifier()`, ardından CUID ile birlikte `identify()` fonksiyonunu çağırın. ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let distinctId = PostHogSDK.shared.getDistinctId() try await Adapty.setIntegrationIdentifier( key: "posthog_distinct_user_id", value: distinctId ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("posthog_distinct_user_id", PostHog.distinctId()) { error -> if (error != null) { // handle the error } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("posthog_distinct_user_id", PostHog.distinctId(), error -> { if (error != null) { // handle the error } }); ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers try { final distinctId = await Posthog().getDistinctId(); await Adapty().setIntegrationIdentifier( key: "posthog_distinct_user_id", value: distinctId, ); } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity" default> Unity için resmi bir PostHog SDK'sı bulunmamaktadır. </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... const posthog = usePostHog(); // ... try { await adapty.setIntegrationIdentifier("posthog_distinct_user_id", posthog.getDistinctId()); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> Adapty artık PostHog'a event gönderecek ve oradan attribution alacak. --- # File: splitmetrics --- --- title: "SplitMetrics Acquire" description: "Abonelik A/B testi ve optimizasyonu için SplitMetrics'i Adapty ile kullanın." --- [SplitMetrics Acquire](https://splitmetrics.com/acquire/) entegrasyonu sayesinde Apple Search Ads reklamlarınızın aboneliklerden ne kadar gelir getirdiğini tam olarak görebilirsiniz. Ayrıca kullanıcılarınızı aylarca takip ederek reklamlarınızın zaman içinde ne kadar kazandırdığını öğrenebilirsiniz. Ayrıca Adapty, Apple Search Ads attribution verilerine dayanarak özel panolar ve otomasyon oluşturabilmeniz için SplitMetrics Acquire'a [abonelik etkinlikleri](events) gönderir. Attribution verisi Adapty'ye eklenmez; zira ASA'dan doğrudan ihtiyacımız olan her şeye zaten sahibiz. ## SplitMetrics Acquire entegrasyonu nasıl kurulur \{#how-to-set-up-splitmetrics-acquire-integration\} SplitMetrics Acquire'ı entegre etmek için [Integrations > SplitMetrics Acquire](https://app.adapty.io/integrations/splitmetrics) sayfasına gidin ve kimlik bilgilerini girin. <img src="/assets/shared/img/8255349-CleanShot_2023-08-14_at_17.39.422x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> SplitMetrics Acquire hesabınızı açın, MMP logolarından birinin üzerine gelin ve **Settings** düğmesine tıklayın. İletişim kutusundaki **5.** madde altında Client ID'nizi bulun, kopyalayın ve Adapty'ye **Client ID** olarak yapıştırın. <img src="/assets/shared/img/4d0b2b6-Adapty.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/4f8d0b8-AdaptyGuide.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Entegrasyonu kullanmak için Apple App ID'nizi de girmeniz gerekecek. App ID'nizi bulmak için App Store Connect'te uygulama sayfanızı açın, **General** bölümündeki **App Information** sayfasına gidin ve ekranın sol alt kısmındaki **Apple ID**'yi bulun. <img src="/assets/shared/img/61578ee-CleanShot_2022-04-20_at_17.55.03.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Etkinlikler ve etiketler \{#events-and-tags\} Kimlik bilgilerinin altında, Adapty'den SplitMetrics Acquire'a gönderebileceğiniz üç grup etkinlik yer alır. İhtiyacınız olanları açmanız yeterli. Adapty'nin sunduğu etkinliklerin tam listesini [buradan](events) inceleyebilirsiniz. <img src="/assets/shared/img/1b0c777-CleanShot_2023-08-11_at_14.56.362x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'nin sağladığı varsayılan etkinlik adlarını kullanmanızı öneririz. Ancak etkinlik adlarını ihtiyaçlarınıza göre değiştirebilirsiniz. Adapty, sunucudan sunucuya entegrasyon aracılığıyla SplitMetrics Acquire'a abonelik etkinlikleri gönderir; böylece tüm abonelik etkinliklerini SplitMetrics kontrol panelinizde görüntüleyebilirsiniz. ## SDK yapılandırması \{#sdk-configuration\} SDK tarafında herhangi bir şey yapılandırmanıza gerek yok; ancak daha iyi doğruluk için Adapty'ye `customerUserId` göndermenizi öneririz. :::warning [Apple Search Ads](apple-search-ads)'i Adapty'de yapılandırdığınızdan ve [kimlik bilgilerini yüklediğinizden](https://app.adapty.io/settings/apple-search-ads) emin olun; bunlar olmadan SplitMetrics Acquire çalışmaz. ::: ## Sorun giderme \{#troubleshooting\} Doğru kuruluma rağmen SplitMetrics Acquire entegrasyonu çalışmıyorsa: - [App Settings -> Apple Search Ads sekmesinde](https://app.adapty.io/settings/apple-search-ads) **Receive Apple Search Ads attribution in Adapty** geçişinin etkin olduğundan, Adapty'de [Apple Search Ads](apple-search-ads)'in yapılandırıldığından ve [kimlik bilgilerinin yüklendiğinden](https://app.adapty.io/settings/apple-search-ads) emin olun; bunlar olmadan SplitMetrics çalışmaz. - Profillerin organik olmayan ASA attribution'ına sahip olduğundan emin olun. Yalnızca ayrıntılı, organik olmayan ASA attribution'ına sahip profiller etkinliklerini Adapty'ye iletir. ## SplitMetrics Acquire etkinlik yapısı \{#splitmetrics-acquire-event-structure\} Adapty, etkinlikleri sorgu parametreleri kullanarak GET isteğiyle SplitMetrics Acquire'a gönderir. Her etkinlik şu şekilde yapılandırılmıştır: ```json { "source": "Apple Search Ads", "app_id": "123456789", "name": "subscription_renewed", "type": "subscription_renewed", "revenue": 9.99, "currency": "USD", "tap_time": "2024-03-01 12:00:00", "open_time": "2024-03-01 12:05:00", "event_time": "2024-03-02 12:00:00", "adaccount_id": "123456", "campaign_id": "123456789", "adgroup_id": "123456789", "keyword_id": "123456789", "creative_set_id": "123456789", "Ad_id": "123456789", "country_or_region": "US", "conversion_type": "Download", "user_id": "user_12345", "att_status": "3", "device_type": "iphone", "app_version": "1.2.3", "sdk_version": "2.10.0", "ios_version": "17.2", "event_value": "{\"vendor_product_id\":\"yearly.premium.6999\",\"original_transaction_id\":\"GPA.3383...\"}", "event_id": "123e4567-e89b-12d3-a456-426614174000" } ``` Parametreler: | Parametre | Tür | Açıklama | |:--------------------|:-------|:----------------------------------------------------------------------------------------------------------------------| | `source` | String | Her zaman "Apple Search Ads". | | `app_id` | String | Apple App ID. | | `name` | String | Etkinlik adı (Adapty etkinliğinden eşlenir). | | `type` | String | Etkinlik türü (`name` ile aynı). | | `revenue` | Float | Gelir miktarı. | | `currency` | String | Para birimi kodu. | | `tap_time` | String | Reklama tıklanma tarihi ve saati. | | `open_time` | String | Uygulamanın açıldığı (kurulduğu) tarih ve saat. | | `event_time` | String | Etkinliğin gerçekleştiği tarih ve saat. | | `adaccount_id` | String | ASA Organizasyon ID'si. | | `campaign_id` | String | ASA Kampanya ID'si. | | `adgroup_id` | String | ASA Reklam Grubu ID'si. | | `keyword_id` | String | ASA Anahtar Kelime ID'si. | | `creative_set_id` | String | ASA Kreatif Set ID'si. | | `Ad_id` | String | ASA Reklam ID'si. | | `country_or_region` | String | Mağaza ülkesi veya bölgesi. | | `conversion_type` | String | Dönüşüm türü (örn. "Download"). | | `user_id` | String | Müşteri Kullanıcı ID'si veya Adapty Profil ID'si. | | `att_status` | String | İzleme kullanım durumu (0-3). | | `device_type` | String | Cihaz türü (örn. "iphone", "ipad"). | | `app_version` | String | Uygulama sürümü. | | `sdk_version` | String | Adapty SDK sürümü. | | `ios_version` | String | iOS sürümü. | | `event_value` | String | Mevcut tüm [etkinlik ayrıntılarını](webhook-event-types-and-fields#for-most-event-types) içeren JSON dizesi. | | `event_id` | String | Benzersiz etkinlik ID'si (UUID). | --- # File: braze --- --- title: "Braze" description: "Adapty ile Braze'i entegre ederek müşteri etkileşimini ve push bildirimlerini kolaylaştırın." --- En iyi müşteri etkileşim çözümlerinden biri olan [Braze](https://www.braze.com/), push bildirimleri, e-posta, SMS ve uygulama içi mesajlaşma için geniş bir araç yelpazesi sunar. Adapty'yi Braze ile entegre ederek tüm abonelik etkinliklerinize tek bir yerden erişebilir ve bu etkinliklere dayalı otomatik iletişim tetikleyebilirsiniz. Adapty, tüm mağazalardan [abonelik etkinliklerini](events) tek bir yerde takip etmenizi sağlayan eksiksiz bir veri seti sunar ve bu veriyi Braze'deki kullanıcı profillerinizi güncellemek için kullanabilirsiniz. Adapty ile abonelerinizin davranışlarını kolayca izleyebilir, tercihlerini öğrenebilir ve bu bilgileri hedefli ve etkili bir iletişim kurmak için kullanabilirsiniz. Bu entegrasyon sayesinde abonelik etkinliklerini Braze kontrol panelinizde takip edebilir ve bunları [edinim kampanyalarınızla](https://www.braze.com/product/journey-orchestration) ilişkilendirebilirsiniz. Adapty, abonelik etkinliklerini, kullanıcı özelliklerini ve satın alımları Braze'e aktarır; böylece aşağıda açıklanan kısa ve kolay entegrasyonun ardından Braze push bildirimleriyle müşterilerinizle hedefli iletişim kurabilirsiniz. ## Braze entegrasyonu nasıl kurulur \{#how-to-set-up-braze-integration\} Braze'i entegre etmek için [Integrations -> Braze](https://app.adapty.io/integrations/braze) sayfasına gidin, geçişi açın ve alanları doldurun. Entegrasyon sürecinin ilk adımı, Braze ile Adapty profilleriniz arasında bağlantı kurabilmek için gerekli kimlik bilgilerini sağlamaktır. Entegrasyonun düzgün çalışması için **REST API Key**, **Braze Instance ID** ve iOS ile Android için **App ID**'lere ihtiyacınız olacak: <img src="/assets/shared/img/5f1e62c-adapty_braze.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **REST API Key**, **Braze Dashboard** → **Settings** → **API Keys** bölümünden oluşturulabilir. Anahtarı oluştururken `users.track` iznine sahip olduğundan emin olun: <img src="/assets/shared/img/b5fdf16-adapty_braze_create_api_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/1e5b4b8-adapty_braze_api_key_users_track.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Braze Instance ID**'yi öğrenmek için Braze Dashboard URL'nize bakın ve instance ID'nin belirtildiği [Braze Docs](https://www.braze.com/docs/api/basics/#endpoints) bölümüne gidin. US-03, EU-01 gibi bölgesel bir biçimde olmalıdır. 3. iOS ve Android App ID'leri de Braze Dashboard → **Settings** → **API Keys** bölümünden bulunabilir. Buradan kopyalayın: <img src="/assets/shared/img/1e6d21b-adapty_braze_app_ids.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Etkinlikler, kullanıcı özellikleri ve satın alımlar \{#events-user-attributes-and-purchases\} Kimlik bilgilerinin altında, Adapty'den Braze'e gönderebileceğiniz üç grup etkinlik bulunur. İhtiyacınız olanları açmanız yeterli. Braze'e gönderilecek etkinliklerin adlarını da değiştirebilirsiniz. Adapty'nin sunduğu etkinliklerin tam listesine [buradan](events) ulaşabilirsiniz: <img src="/assets/shared/img/702e628-adapty_braze_events_names.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty, abonelik etkinliklerini ve kullanıcı özelliklerini sunucudan sunucuya entegrasyon aracılığıyla Braze'e gönderir; böylece bunları Braze kontrol panelinizde görüntüleyebilir ve kampanyalarınızı buna göre yapılandırabilirsiniz. Deneme dönüşümleri ve yenilemeler gibi gelir içeren etkinlikler için Adapty bu bilgiyi Braze'e satın alım olarak gönderir. Braze'e gönderilen etkinlik özelliklerinin tam spesifikasyonlarına [buradan](messaging#event-properties) ulaşabilirsiniz. :::note Kullanışlı kullanıcı özellikleri Adapty, Braze entegrasyonu için varsayılan olarak bazı kullanıcı özelliklerini gönderir. İhtiyacınıza en uygun olanı belirlemek için aşağıdaki listeye başvurabilirsiniz. ::: | Kullanıcı özelliği | Tür | Değer | |--------------|----|-----| | `adapty_customer_user_id` | String | Müşteri tarafından tanımlanan kullanıcının benzersiz tanımlayıcısının değerini içerir. Hem Adapty [Kontrol Paneli'nde](profiles-crm) hem de Braze'de bulunabilir. | | `adapty_profile_id` | String | Adapty [Kontrol Paneli'nde](profiles-crm) bulunabilen Adapty Kullanıcı Profili ID'sinin benzersiz tanımlayıcısının değerini içerir. | | `environment` | String | <p>Kullanıcının sandbox mı yoksa production ortamında mı işlem yaptığını gösterir.</p><p></p><p>Değerler `Sandbox` veya `Production` şeklindedir.</p> | | `store` | String | <p>Satın alma için kullanılan mağazanın adını içerir.</p><p></p><p>Olası değerler:</p><p>`app_store` veya `play_store`.</p> | | `vendor_product_id` | String | <p>Apple/Google mağazasındaki Ürün ID'sinin değerini içerir.</p><p></p><p>Örn. org.locals.12345</p> | | `subscription_expires_at` | String | <p>En son aboneliğin bitiş tarihini içerir.</p><p></p><p>Değer biçimi:</p><p>YYYY-MM-DDTHH:mm:ss.SSS+TZ</p><p>Örn. 2023-02-15T17:22:03.000+0000</p> | | `active_subscription` | String | Herhangi bir satın alma/yenileme etkinliğinde `true`, abonelik sona erdiyse `false` olarak ayarlanır. | | `period_type` | String | <p>Satın alma veya yenileme için en son dönem türünü gösterir.</p><p></p><p>Olası değerler:</p><p>Deneme dönemi için `trial`, diğerleri için `normal`.</p> | Tüm ondalıklı değerler tam sayıya yuvarlanır. String değerler değişmeden kalır. Önceden tanımlanmış etiket listesine ek olarak, etiketleri kullanarak [özel özellikler](segments#custom-attributes) göndermek de mümkündür. Bu, etiketle birlikte gönderilebilecek veri türünde daha fazla esneklik sağlar ve bir ürün veya hizmete ilişkin belirli bilgilerin takibinde kullanışlıdır. Kullanıcı [entegrasyon sayfasından](https://app.adapty.io/integrations/braze) **Send user attributes** onay kutusunu işaretlerse tüm özel kullanıcı özellikleri otomatik olarak Braze'e gönderilir. ## SDK Yapılandırması \{#sdk-configuration\} Adapty ve Braze'deki kullanıcı profillerini bağlamak için Braze SDK'yı Adapty ile aynı müşteri kullanıcı ID'siyle yapılandırmanız ya da `.changeUser()` metodunu kullanmanız gerekir: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers let braze = Braze(configuration: configuration) braze.changeUser(userId: "adapty_customer_user_id") ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Braze.getInstance(context).changeUser("adapty_customer_user_id") ``` </TabItem> </Tabs> --- # File: onesignal --- --- title: "OneSignal" description: "Kullanıcı etkileşimini artırmak için OneSignal'ı Adapty ile entegre edin." --- [OneSignal](https://onesignal.com/), push bildirimler, e-posta, SMS ve uygulama içi mesajlaşma sunan önde gelen bir müşteri etkileşim platformudur. Adapty'yi OneSignal ile entegre etmek, tüm abonelik olaylarınıza tek bir yerden erişmenizi ve bu olaylara dayalı otomatik iletişim tetiklemenizi sağlar. Adapty ile birden fazla mağazada [abonelik olaylarını](events) takip edebilir, kullanıcı davranışlarını analiz edebilir ve bu verileri daha hedefli iletişim için kullanabilirsiniz. Bu entegrasyon, OneSignal kontrol panelinizde abonelik olaylarını izlemenize ve bunları [edinim kampanyalarınızla](https://documentation.onesignal.com/docs/en/automated-messages) eşleştirmenize yardımcı olur. Adapty, abonelik olaylarına göre OneSignal tag'lerini güncelleyerek minimum kurulumla kişiselleştirilmiş push bildirimleri göndermenizi sağlar. **Entegrasyon özellikleri** | Entegrasyon özelliği | Açıklama | | :------------------------- | :----------------------------------------------------------- | | Zamanlama | Gerçek zamanlı güncellemeler | | Veri yönü | Tek yönlü: Adapty'den OneSignal sunucusuna | | Adapty entegrasyon noktası | <ul><li>Mobil uygulama kodunda OneSignal ve Adapty SDK'ları</li><li>Adapty sunucusu</li></ul>| ## OneSignal entegrasyonunu kurma \{#setting-up-one-signal-integration\} Entegrasyonu kurmak için: 1. Adapty Kontrol Paneli'nde [Integrations → OneSignal](https://app.adapty.io/integrations/onesignal) sayfasını açın. <img src="/assets/shared/img/onesignal-on.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Entegrasyon geçişini etkinleştirin. 3. **OneSignal App ID**'nizi girin. OneSignal entegrasyonunu kurmak için Adapty kontrol panelinizde [Integrations -> OneSignal](https://app.adapty.io/integrations/onesignal) sayfasına gidin, geçişi açın ve entegrasyon kimlik bilgilerini yapılandırın. ## OneSignal App ID'nizi alma \{#retrieving-your-onesignal-app-id\} **OneSignal App ID**'nizi [OneSignal Dashboard](https://dashboard.onesignal.com/login)'da bulun: 1. **Settings** → **Keys & IDs** bölümüne gidin. <img src="/assets/shared/img/onesignal-dashboard.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **OneSignal App ID**'nizi kopyalayın ve Adapty Kontrol Paneli'ndeki **App ID** alanına yapıştırın. <img src="/assets/shared/img/onesignal-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> OneSignal ID hakkında daha fazla bilgiye [bu dokümantasyondan](https://documentation.onesignal.com/docs/en/keys-and-ids) ulaşabilirsiniz. ### Olayları yapılandırma \{#configuring-events\} Adapty, OneSignal'a üç grup olay göndermenize olanak tanır. İhtiyacınız olanları Adapty Kontrol Paneli'nden açın. Mevcut olayların tamamını ayrıntılı açıklamalarıyla [buradan](events) görüntüleyebilirsiniz. <img src="/assets/shared/img/onesignal.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty, abonelik olaylarını sunucudan sunucuya entegrasyon aracılığıyla OneSignal'a göndererek tüm abonelikle ilgili aktivitelerinizi OneSignal'da takip etmenizi sağlar. :::warning 17 Nisan 2023'ten itibaren OneSignal'ın Ücretsiz Planı bu entegrasyonu desteklememektedir. Yalnızca **Growth**, **Professional** ve **daha üst** planlarda kullanılabilir. Ayrıntılar için [OneSignal Fiyatlandırma](https://onesignal.com/pricing) sayfasına bakın. ::: ## Özel etiketler \{#custom-tags\} Bu entegrasyon, Adapty kullanıcılarınıza çeşitli özellikleri etiket olarak atar ve günceller; bu etiketler daha sonra OneSignal'a gönderilir. İhtiyaçlarınıza en uygun olanları bulmak için aşağıdaki etiket listesine bakın. :::warning OneSignal'ın bir etiket sınırı vardır. Bu sınır hem Adapty tarafından oluşturulan etiketleri hem de OneSignal'daki mevcut etiketleri kapsar. Sınırın aşılması, olay gönderilirken hatalara yol açabilir. ::: | Etiket | Tür | Açıklama | |---|----|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `adapty_customer_user_id` | String | Kullanıcının uygulamanızdaki benzersiz tanımlayıcısı. Sisteminizde, Adapty'de ve OneSignal'da tutarlı olmalıdır. | | `adapty_profile_id` | String | [Adapty Kontrol Paneli](profiles-crm)'nde görüntülenebilen Adapty kullanıcı profili ID'si. | | `environment` | String | Kullanıcının mevcut ortamını belirten `Sandbox` veya `Production`. | | `store` | String | Ürünün satın alındığı mağaza. Seçenekler: **app_store**, **play_store**, **stripe** veya [özel mağazanızın](custom-store) adı. | | `vendor_product_id` | String | Uygulama mağazasındaki ürün ID'si (ör. `org.locals.12345`). | | `subscription_expires_at` | String | En son aboneliğin bitiş tarihi (`YYYY-MM-DDTHH:MM:SS+0000`, ör. `2023-02-10T17:22:03.000000+0000`). | | `last_event_type` | String | [Adapty olay listesinden](events) en son olay türü.<br/> Şunlara dikkat edin:<br/>- **Subscription expired** olayı için Adapty, `last_event_type` özelliğini `subscription_cancelled` olarak gönderir.<br/>- **Trial renew canceled** için – `auto_renew_off` olarak<br/>- **Subscription renew canceled** için – `auto_renew_off_subscription` olarak | | `purchase_date` | String | Son işlem tarihi (`YYYY-MM-DDTHH:MM:SS+0000`, ör. `2023-02-10T17:22:03.000000+0000`). | | `active_subscription` | String | Kullanıcının aktif bir aboneliği varsa `true`, aboneliği sona erdiyse `false`. | | `period_type` | String | Satın alma veya yenileme için en son dönem türünü belirtir. Olası değerler: deneme dönemi için `trial`, diğer tüm durumlar için `normal`. | Tüm ondalıklı değerler tam sayıya yuvarlanır. Dizeler değişmeden kalır. Önceden tanımlanmış etiketlere ek olarak, [özel nitelikleri](segments#custom-attributes) etiket olarak gönderebilir ve dahil ettiğiniz verilerde daha fazla esneklik sağlayabilirsiniz. Bu, ürününüz veya hizmetinizle ilgili belirli ayrıntıları takip etmek için kullanışlıdır. Özel kullanıcı nitelikleri, [entegrasyon sayfasında](https://app.adapty.io/integrations/onesignal) **Send user attributes** onay kutusu etkinleştirildiğinde otomatik olarak OneSignal'a gönderilir. İşaret kaldırıldığında Adapty tam olarak 10 etiket gönderir. İşaretlendiğinde ise 10'dan fazla etiket gönderilebilir, bu da daha gelişmiş veri yakalamaya olanak tanır. ## SDK yapılandırması \{#sdk-configuration\} OneSignal ile Adapty'yi entegre etmenin iki yolu vardır: 1. **Eski yöntem (v5 öncesi):** [OneSignal SDK v5](https://github.com/OneSignal/OneSignal-iOS-SDK/releases/tag/5.0.0)'te kullanımdan kaldırılan `playerId` kullanır. 2. **Güncel yöntem (v5+):** `subscriptionId` kullanır. :::warning Adapty'ye `playerId` (OneSignal SDK v5 öncesi için) veya `subscriptionId` (OneSignal SDK v5+ için) gönderdiğinizden emin olun. Bu yapılmadan OneSignal etiketleri güncellenmez ve entegrasyon düzgün çalışmaz. ::: <Tabs groupId="current-version" queryString> <TabItem value="v5+" label="OneSignal SDK v5+ (current)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers // SubscriptionID OneSignal.Notifications.requestPermission({ accepted in Task { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.oneSignalSubscriptionId(OneSignal.User.pushSubscription.id)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "one_signal_subscription_id", value: OneSignal.User.pushSubscription.id ) } }, fallbackToSettings: true) ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // SubscriptionID val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver { override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) { Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error -> if (error != null) { // handle the error } } } } ``` </TabItem> <TabItem value="java" label="(Android) Java" default> ```java showLineNumbers // SubscriptionID IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> { Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> { if (error != null) { // handle the error } }); }; ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers // 1. Since OneSignal.User.pushSubscription.id may return null if called too early, // OneSignal suggests to listen for the updates: OneSignal.User.pushSubscription.addObserver((state) { if (state.current.optedIn) { // now you can try to retrieve subscriptionId } }); // 2. Then you can push subscriptionId to Adapty: final subscriptionId = OneSignal.User.pushSubscription.id; if (subscriptionId != null) { await Adapty().setIntegrationIdentifier(key: "one_signal_subscription_id", value: subscriptionId); } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; using OneSignalSDK; var pushUserId = OneSignal.Default.PushSubscriptionState.userId; Adapty.SetIntegrationIdentifier( "one_signal_player_id", pushUserId, (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers OneSignal.User.pushSubscription.addEventListener('change', (subscription) => { const subscriptionId = subscription.current.id; if (subscriptionId) { adapty.setIntegrationIdentifier("one_signal_subscription_id", subscriptionId); } }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="pre-v5" label="OneSignal SDK v. up to 4.x (legacy)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers // PlayerID // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { Task { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.oneSignalPlayerId(playerId)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "one_signal_player_id", value: playerId ) } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // PlayerID val osSubscriptionObserver = OSSubscriptionObserver { stateChanges -> stateChanges?.to?.userId?.let { playerId -> Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error -> if (error != null) { // handle the error } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers // PlayerID OSSubscriptionObserver osSubscriptionObserver = stateChanges -> { OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null; String playerId = to != null ? to.getUserId() : null; if (playerId != null) { Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> { if (error != null) { // handle the error } }); } }; ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers // PlayerID (pre-v5 OneSignal SDK) // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { Task { try await Adapty.setIntegrationIdentifier( key: "one_signal_player_id", value: playerId ) } } } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers OneSignal.addSubscriptionObserver(event => { const playerId = event.to.userId; adapty.setIntegrationIdentifier("one_signal_player_id", playerId); }); ``` </TabItem> </Tabs> </TabItem> </Tabs> OneSignal dokümantasyonunda daha fazla bilgi edinin: - [Push abonelik ID'si](https://documentation.onesignal.com/docs/en/mobile-sdk-reference#user-pushsubscription-id) - [Push abonelik değişiklikleri](https://documentation.onesignal.com/docs/en/mobile-sdk-reference#addobserver-push-subscription-changes) ## Birden fazla cihazı yönetme \{#dealing-with-multiple-devices\} Bir kullanıcının birden fazla cihazı varsa satın alma olaylarını ve abonelikleri takip etmek güçleşebilir. OneSignal, bunu [harici kullanıcı ID'leri](https://documentation.onesignal.com/docs/en/users) aracılığıyla yönetmenin bir yolunu sunar. Kullanıcı verilerini cihazlar arasında tutarlı tutmak için: 1. **Sunucu tarafında** farklı cihazları eşleştirin ve bu verileri OneSignal'a gönderin. 2. OneSignal'da Adapty'nin [customer_user_id](identifying-users)'sini [externalUserId](https://documentation.onesignal.com/docs/en/users#external-id) olarak kullanın. Uygulamanızın bir kayıt sistemi yoksa, kullanıcının cihazları arasında tutarlı kalan başka bir benzersiz tanımlayıcı kullanmayı düşünün. Kullanıcı tanımlayıcısının tüm cihazlarda tutarlı olmasını sağlamak ve bir kullanıcının ID'si değiştiğinde OneSignal'ı güncellemek önemlidir. Bu, kullanıcı aktivitesini ve abonelikleri takip etmeyi kolaylaştırır, tutarlı mesajlaşma sağlar ve daha doğru analizler ile daha iyi bir kullanıcı deneyimine olanak tanır. Daha fazla ayrıntı için OneSignal'ın [harici kullanıcı ID dokümantasyonuna](https://documentation.onesignal.com/docs/en/users) bakın. --- # File: pushwoosh --- --- title: "Pushwoosh" description: "Pushwoosh'u Adapty ile entegre ederek push bildirimi takibini sorunsuz yapın." --- Adapty, abonelik olaylarını kullanarak [Pushwoosh](https://www.pushwoosh.com/) profil etiketlerini günceller. Bu sayede aşağıda açıklanan kısa ve kolay entegrasyon ayarlarını yaptıktan sonra push bildirimleriyle hedefli iletişim kurabilirsiniz. ## Pushwoosh entegrasyonu nasıl kurulur \{#how-to-set-up-pushwoosh-integration\} Pushwoosh'u entegre etmek için [**Integrations** -> **Pushwoosh**](https://app.adapty.io/integrations/pushwoosh) sayfasına gidin, geçişi kapalıdan açık konuma getirin ve alanları doldurun. Öncelikle Pushwoosh ve Adapty profilleriniz arasındaki bağlantıyı kurmak için kimlik bilgilerini girin. Pushwoosh uygulama kimliği ve kimlik doğrulama token'ı gereklidir. <img src="/assets/shared/img/64e48a1-CleanShot_2023-08-18_at_11.13.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **App ID**, Pushwoosh kontrol panelinizde bulunabilir. <img src="/assets/shared/img/ee27687-CleanShot_2023-08-18_at_14.37.442x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Auth token**, Pushwoosh Ayarları'ndaki API Access bölümünde bulunabilir. <img src="/assets/shared/img/50e634b-CleanShot_2023-08-18_at_14.35.022x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Olaylar ve etiketler \{#events-and-tags\} Kimlik bilgilerinin altında, Adapty'den Pushwoosh'a gönderebileceğiniz üç grup olay yer almaktadır. İhtiyacınız olanları açmanız yeterli. Pushwoosh'a gönderim için olay adlarını da değiştirebilirsiniz. Adapty'nin sunduğu olayların tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/392dc31-screencapture-app-adapty-io-integrations-pushwoosh-2023-08-22-13_31_07.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty, sunucudan sunucuya entegrasyon aracılığıyla abonelik olaylarını Pushwoosh'a gönderir ve tüm abonelik olaylarını Pushwoosh Kontrol Panelinizde görüntülemenizi sağlar. :::note Özel etiketler Adapty ile Pushwoosh entegrasyonunda kendi özel etiketlerinizi de kullanabilirsiniz. Hangi etiketin ihtiyacınıza en uygun olduğunu belirlemek için aşağıdaki etiket listesine başvurabilirsiniz. ::: | Etiket | Tür | Değer | |---|----|-----| | `adapty_customer_user_id` | String | Pushwoosh tarafında bulunan kullanıcının benzersiz tanımlayıcısının değerini içerir. | | `adapty_profile_id` | String | Adapty [kontrol panelinde](profiles-crm) bulunabilen kullanıcının Adapty Kullanıcı Profili kimliğinin benzersiz tanımlayıcı değerini içerir. | | `environment` | String | <p>Kullanıcının sandbox mı yoksa production ortamında mı çalıştığını belirtir.</p><p></p><p>Değerler `Sandbox` veya `Production` şeklindedir.</p> | | `store` | String | <p>Satın alma işleminde kullanılan Store adını içerir.</p><p></p><p>Olası değerler:</p><p>`app_store` veya `play_store`.</p> | | `vendor_product_id` | String | <p>Apple/Google mağazasındaki Ürün Kimliğinin değerini içerir.</p><p></p><p>Örn. org.locals.12345</p> | | `subscription_expires_at` | String | <p>En son aboneliğin sona erme tarihini içerir.</p><p></p><p>Değer formatı:</p><p>yıl-ay günTsaat:dakika:saniye</p><p>Örn. 2023-02-10T17:22:03.000000+0000</p> | | `last_event_type` | String | Entegrasyon için etkinleştirdiğiniz standart [Adapty olayları](events) listesinden alınan son olayın türünü belirtir. | | `purchase_date` | String | <p>Son işlemin (orijinal satın alma veya yenileme) tarihini içerir.</p><p></p><p>Değer formatı:</p><p>yıl-ay günTsaat:dakika:saniye</p><p>Örn. 2023-02-10T17:22:03.000000+0000</p> | | `original_purchase_date` | String | <p>İşleme göre ilk satın alma tarihini içerir.</p><p></p><p>Değer formatı:</p><p>yıl-ay günTsaat:dakika:saniye</p><p>Örn. 2023-02-10T17:22:03.000000+0000</p> | | `active_subscription` | String | Herhangi bir satın alma/yenileme olayında `true`, abonelik sona erdiğinde `false` olarak ayarlanır. | | `period_type` | String | <p>Satın alma veya yenileme için en son dönem türünü belirtir.</p><p></p><p>Olası değerler:</p><p>Deneme dönemi için `trial`, geri kalanı için `normal`.</p> | Tüm float değerler int'e yuvarlanır. String değerler aynı kalır. Önceden tanımlanmış etiket listesine ek olarak, [özel nitelikler](segments#custom-attributes) etiketler aracılığıyla da gönderilebilir. Bu, etikete eklenebilecek veri türünde daha fazla esneklik sağlar ve bir ürün veya hizmete ilişkin belirli bilgilerin takibi için faydalı olabilir. Tüm özel kullanıcı nitelikleri, kullanıcı [entegrasyon sayfasındaki](https://app.adapty.io/integrations/pushwoosh) **Send user custom attributes** onay kutusunu işaretlerse otomatik olarak Pushwoosh'a gönderilir. ## SDK yapılandırması \{#sdk-configuration\} Adapty'yi Pushwoosh ile ilişkilendirmek için `HWID` değerini bize göndermeniz gerekir: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "pushwoosh_hwid", value: Pushwoosh.sharedInstance().getHWID() ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> { if (error != null) { // handle the error } }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; try { await Adapty().setIntegrationIdentifier( key: "pushwoosh_hwid", value: hwid, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "pushwoosh_hwid", Pushwoosh.Instance.HWID, (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... try { await adapty.setIntegrationIdentifier("pushwoosh_hwid", hwid); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> --- # File: slack --- --- title: "Slack" description: "Slack'i Adapty ile entegre ederek abonelik olayları hakkında anlık bildirimler alın." --- [Slack](https://slack.com/), tanıtıma gerek duymayan bir iş yeri mesajlaşma ve verimlilik platformudur. Bu entegrasyon sayesinde Adapty tarafından bir gelir olayı kaydedildiğinde Slack'te bildirim alabilirsiniz. MRR'ınızın her artışını takip etmek ya da deneme iptalleri, faturalama sorunları, iadeler ve daha fazlası için gözetleme yapmak istiyorsanız bu özellik işinize yarayacaktır. ## Slack entegrasyonu nasıl kurulur \{#how-to-set-up-slack-integration\} Yapmanız gerekenler: - Slack çalışma alanınızda bir uygulama oluşturmak - Mesaj gönderme iznini vermek - Gerekli bilgileri [Integrations → Slack](https://app.adapty.io/integrations/slack) üzerinden Adapty'ye sağlamak. ### 1\. Slack'te uygulama oluşturma \{#1-create-an-app-in-slack\} 1. [Slack API kontrol paneline](https://api.slack.com/apps) gidin ve aşağıdaki gibi bir uygulama oluşturun: <img src="/assets/shared/img/f43aedc-CleanShot_2024-01-04_at_18.27.412x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/08fa9e6-CleanShot_2024-01-04_at_18.28.142x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Uygulamaya istediğiniz bir ad verin (örneğin `Adapty`) ve çalışma alanınıza ekleyin: <img src="/assets/shared/img/5002bb1-CleanShot_2024-01-04_at_18.29.132x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 2\. Gönderi iznini verin ve uygulamanız için token alın \{#2-give-permission-to-post-and-get-a-token-for-your-app\} Slack'teki uygulamanızın sayfasına yönlendirileceksiniz. 1. Aşağı kaydırın ve **Permissions**'a tıklayın: <img src="/assets/shared/img/9750451-CleanShot_2024-01-04_at_18.48.072x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Yönlendirmeden sonra **Scopes** bölümüne gidin ve **Add an OAuth Scope**'a tıklayın: <img src="/assets/shared/img/db5b5f4-CleanShot_2024-01-04_at_18.50.262x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Kanallarınıza mesaj gönderebilmek ve mesajları özelleştirebilmek için `chat:write`, `chat:write.public` ve `chat:write.customize` izinlerini verin: <img src="/assets/shared/img/d97ccb9-CleanShot_2024-01-04_at_18.51.572x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Sayfanın en üstüne dönün ve **Install to Workspace**'e tıklayın: <img src="/assets/shared/img/14608e3-CleanShot_2024-01-04_at_19.17.58.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Açılan ekranda **Allow**'a tıklayın: <img src="/assets/shared/img/143967e-CleanShot_2024-01-04_at_18.53.292x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adımın ardından aynı sayfaya yönlendirileceksiniz; ancak artık bir OAuth Token (`xoxb-...`) göreceksiniz. Kurulumu tamamlamak için ihtiyaç duyulan tam olarak budur: <img src="/assets/shared/img/59b33ee-CleanShot_2024-01-04_at_18.55.222x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 3\. Adapty'de entegrasyonu yapılandırma \{#3-configure-the-integration-in-adapty\} 1. [**Integrations** → **Slack**](https://app.adapty.io/integrations/slack) sayfasına gidin: <img src="/assets/shared/img/b4ffd71-CleanShot_2024-01-04_at_19.05.222x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Önceki adımdan aldığınız `xoxb-...` token'ını yapıştırın ve uygulamanın hangi kanallara mesaj göndereceğini seçin. Entegrasyonu yalnızca production, yalnızca sandbox ya da her iki ortamdan gelen olayları alacak şekilde ayarlayabilirsiniz. Ayrıca hangi para biriminde gönderi yapılacağını da seçebilirsiniz (orijinal veya USD'ye dönüştürülmüş). :::note Adapty'den özel bir kanala mesaj göndermek istiyorsanız, Slack'te oluşturduğunuz `Adapty` uygulamasını o kanala manuel olarak eklemeniz gerekir. Aksi takdirde çalışmayacaktır. ::: 3. Son olarak, **Events** bölümünden hangi olayları almak istediğinizi seçebilirsiniz: <img src="/assets/shared/img/970a7bb-CleanShot_2024-01-04_at_19.09.472x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Hepsi bu kadar! Olaylar belirlediğiniz kanallara gönderilecek. Geçerli olduğunda geliri görebilir ve Adapty'deki müşteri profiline erişebilirsiniz: <img src="/assets/shared/img/852b8c8-CleanShot_2024-01-04_at_19.11.332x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: s3-exports --- --- title: "Amazon S3" description: "Gelişmiş analiz ve raporlama için abonelik verilerini S3'e aktarın." --- Adapty'nin Amazon S3 ile entegrasyonu, etkinlik ve paywall ziyareti verilerini güvenli bir şekilde tek bir merkezi konumda saklamanıza olanak tanır. [Abonelik etkinliklerinizi](events) Amazon S3 bucket'ınıza .csv dosyaları olarak kaydedebilirsiniz. Bu entegrasyonu kurmak için AWS Console ve Adapty Kontrol Paneli'nde birkaç basit adımı takip etmeniz gerekir. :::note Zamanlama Adapty verilerinizi her **24 saatte bir** 04:00 UTC'de gönderir. Her dosya, önceki tam takvim günü (UTC) boyunca oluşturulan event verilerini içerecektir. Örneğin, 8 Mart'ta 04:00 UTC'de otomatik olarak dışa aktarılan veriler, 7 Mart'ta 00:00:00 ile 23:59:59 UTC arasında oluşturulan tüm eventleri içerecektir. ::: ## Amazon S3 entegrasyonunu nasıl kurarsınız \{#how-to-set-up-amazon-s3-integration\} Veri almaya başlamak için aşağıdaki bilgilere ihtiyacınız olacak: 1. Access key ID 2. Secret access key 3. S3 bucket adı 4. S3 bucket içindeki klasör adı :::note İç içe dizinler Amazon S3 bucket adı alanında iç içe dizinler belirtebilirsiniz; örneğin: adapty-events/com.sample-app ::: Amazon S3 entegrasyonu için [**Integrations** -> **Amazon S3**](https://app.adapty.io/integrations/s3) sayfasına gidin, toggle'ı açık konuma getirin ve alanları doldurun. Her şeyden önce, Amazon S3 ile Adapty profilleri arasında bağlantı kurmak için kimlik bilgilerini girin. Adapty Kontrol Paneli'nde bağlantıyı kurmak için aşağıdaki alanlar gereklidir: | Alan | Açıklama | | :--------------------------- | :----------------------------------------------------------- | | **Access Key ID** | AWS hizmetine erişimi doğrulamak için kullanılan benzersiz tanımlayıcı. Bu kimliği indirilen [csv dosyasında](s3-exports#how-to-create-amazon-s3-credentials) bulabilirsiniz. | | **Secret Access Key** | AWS hizmetine erişimi doğrulamak için Access Key ID ile birlikte kullanılan özel anahtar. Bu anahtarı indirilen [csv dosyasında](s3-exports#how-to-create-amazon-s3-credentials) bulabilirsiniz. | | **S3 Bucket Name** | AWS bulutundaki belirli bir S3 bucket'ını tanımlayan, küresel olarak benzersiz ad. S3 bucket'ları, kullanıcıların bulutta dosya ve görsel gibi veri nesnelerini depolamasına ve almasına olanak tanıyan basit bir depolama hizmetidir. | | **Folder Inside the Bucket** | Seçili S3 bucket'ının içinde oluşturmak istediğiniz klasörün adı. S3'ün klasörleri, nesne anahtarı önekleri (yani klasör adları) kullanarak simüle ettiğini unutmayın. | ## Amazon S3 kimlik bilgileri nasıl oluşturulur \{#how-to-create-amazon-s3-credentials\} Bu kılavuz, AWS Console'da gerekli kimlik bilgilerini oluşturmanıza yardımcı olacaktır. ### 1\. Erişim Politikası Oluşturun \{#create-access-policy\} Önce AWS Console'unuzdaki [IAM Policy Dashboard](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/policies) sayfasına gidin ve **Create Policy** seçeneğini tıklayın. <img src="/assets/shared/img/7af075c-CleanShot_2023-03-21_at_10.52.002x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Policy editor** bölümüne aşağıdaki JSON'ı yapıştırın ve `adapty-s3-integration-test` kısmını kendi bucket adınızla değiştirin: ```json showLineNumbers title="Json" { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowListObjectsInBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::adapty-s3-integration-test" }, { "Sid": "AllowAllObjectActions", "Effect": "Allow", "Action": "s3:*Object", "Resource": [ "arn:aws:s3:::adapty-s3-integration-test/*", "arn:aws:s3:::adapty-s3-integration-test" ] }, { "Sid": "AllowBucketLocation", "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::adapty-s3-integration-test" } ] } ``` <img src="/assets/shared/img/d4e474a-CleanShot_2023-03-21_at_10.56.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Politika yapılandırmasını tamamladıktan sonra etiket eklemeyi seçebilirsiniz (isteğe bağlı) ve ardından son adıma geçmek için **Next** düğmesine tıklayın. Bu adımda politikanıza bir ad verip **Create policy** düğmesine tıklayarak oluşturma işlemini tamamlayın. <img src="/assets/shared/img/7dcb02f-CleanShot_2023-03-21_at_11.03.372x.webp" style={{ border: '1px solid #727272', /* kenarlık genişliği ve rengi */ width: '700px', /* resim genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalama hizalama */ }} /> ### 2\. IAM kullanıcısı oluşturun \{#create-iam-user\} Adapty'nin ham veri raporlarını bucket'ınıza yükleyebilmesi için, ilgili bucket'a yazma erişimi olan bir kullanıcıya ait Access Key ID ve Secret Access Key bilgilerini sağlamanız gerekir. Devam etmek için IAM Console'a gidin ve [Users bölümünü](https://console.aws.amazon.com/iamv2/home#/users) seçin. Ardından **Add users** butonuna tıklayın. Kullanıcıya bir isim verin, **Access key – Programmatic access** seçeneğini seçin ve izinlere geçin. <img src="/assets/shared/img/bb612c8-CleanShot_2023-03-21_at_11.12.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bir sonraki adım için **Add user to group** seçeneğini işaretleyin ve ardından **Create group** butonuna tıklayın. <img src="/assets/shared/img/bfd0e80-CleanShot_2023-03-21_at_11.24.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Ardından, Kullanıcı Grubunuza bir ad vermeniz ve daha önce oluşturduğunuz politikayı seçmeniz gerekir. Politikayı seçtikten sonra işlemi tamamlamak için **Create group** düğmesine tıklayın. <img src="/assets/shared/img/df29c12-CleanShot_2023-03-21_at_11.28.052x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Grubu başarıyla oluşturduktan sonra lütfen **seçin** ve bir sonraki adıma geçin. <img src="/assets/shared/img/1f3722e-CleanShot_2023-03-21_at_11.36.192x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu bölümün son adımı olduğundan, **Create User** düğmesine tıklayarak devam edebilirsiniz. Son olarak, kimlik bilgilerini **.csv formatında indirebilir** ya da doğrudan kontrol panelinden kopyalayıp yapıştırabilirsiniz. <img src="/assets/shared/img/bcf35e1-S3created.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Manuel veri dışa aktarımı \{#manual-data-export\} Amazon S3'e otomatik etkinlik verisi dışa aktarımına ek olarak, Adapty manuel dosya dışa aktarımı özelliği de sunar. Bu özellik sayesinde etkinlik verileri için belirli bir zaman aralığı seçerek bunları S3 bucket'ınıza manuel olarak aktarabilirsiniz. Bu, hangi verileri ne zaman dışa aktaracağınız konusunda size daha fazla kontrol imkânı tanır. Belirlenen tarih aralığı, A Tarihi 00:00:00 UTC ile B Tarihi 23:59:59 UTC arasında oluşturulan etkinlikleri dışa aktarmak için kullanılır. <img src="/assets/shared/img/466bd29-CleanShot_2023-03-21_at_12.35.252x.webp" style={{ border: '1px solid #727272', /* kenarlık genişliği ve rengi */ width: '700px', /* görsel genişliği */ display: 'block', /* hizalama için */ margin: '0 auto' /* ortalama hizalama */ }} /> ## Tablo yapısı \{#table-structure\} AWS S3 entegrasyonunda Adapty, işlem olayları ve paywall ziyaretlerine ait geçmiş verileri saklamak için bir tablo sunar. Tablo; kullanıcı profili, gelir ve kazançlar ile kaynak mağaza gibi birçok veri noktasını içerir. Temelde bu tablolar, bir uygulamanın belirli bir zaman diliminde oluşturduğu tüm işlemleri kaydeder. :::warning Bu yapının zamanla büyüyebileceğini unutmayın — bizim veya birlikte çalıştığımız 3. tarafların yeni veriler eklemesiyle. Bu yapıyı işleyen kodunuzun yeterince sağlam olduğundan ve yapının tamamına değil, belirli alanlara dayandığından emin olun. ::: İşte event'ler için tablo yapısı: :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: | Sütun | Açıklama | |---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile_id** | Adapty kullanıcı ID'si. | | **event_type** | Küçük harfli event adı. Event türleri hakkında bilgi almak için [Events](events) bölümüne bakın. | | **event_datetime** | ISO 8601 tarihi. | | **transaction_id** | Satın alma veya yenileme gibi bir işlem için benzersiz tanımlayıcı. | | **original_transaction_id** | Orijinal satın almanın işlem tanımlayıcısı. | | **subscription_expires_at** | Aboneliğin sona erme tarihi. Genellikle gelecekte bir tarihtir. | | **environment** | Sandbox veya Production olabilir. | | **revenue_usd** | USD cinsinden gelir. Boş olabilir. | | **proceeds_usd** | USD cinsinden net hasılat. Boş olabilir. | | **net_revenue_usd** | USD cinsinden net gelir (vergiler düşüldükten sonraki kazanç). Boş olabilir. | | **tax_amount_usd** | USD cinsinden kesilen vergi tutarı. Boş olabilir. | | **revenue_local** | Yerel para biriminde gelir. Boş olabilir. | | **proceeds_local** | Yerel para biriminde net hasılat. Boş olabilir. | | **net_revenue_local** | Yerel para biriminde net gelir (vergiler düşüldükten sonraki kazanç). Boş olabilir. | | **tax_amount_local** | Yerel para biriminde kesilen vergi tutarı. Boş olabilir. | | **customer_user_id** | Geliştirici kullanıcı ID'si. Örneğin kullanıcı UUID'niz, e-posta adresiniz veya başka bir ID olabilir. Ayarlamadıysanız null döner. | | **store** | _app_store_ veya _play_store_ olabilir. | | **product_id** | Apple App Store, Google Play Store veya Stripe'taki ürün ID'si. | | **base_plan_id** | Google Play Store'daki [temel plan ID'si](https://support.google.com/googleplay/android-developer/answer/12154973) veya Stripe'taki [fiyat ID'si](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices). | | **developer_id** | İşlemin gerçekleştiği paywallın geliştirici (SDK) ID'si. | | **ab_test_name** | İşlemin gerçekleştiği A/B testinin adı. | | **ab_test_revision** | İşlemin gerçekleştiği A/B testinin revizyonu. | | **paywall_name** | İşlemin gerçekleştiği paywallın adı. | | **paywall_revision** | İşlemin gerçekleştiği paywallın revizyonu. | | **profile_county** | Adapty tarafından IP'ye göre belirlenen profil ülkesi. | | **install_date** | Kurulumun gerçekleştiği ISO 8601 tarihi. | | **idfv** | iOS cihazlarda [identifierForVendor](https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor) | | **idfa** | iOS cihazlarda [advertisingIdentifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier) | | **advertising_id** | Android İşletim Sistemi tarafından atanan ve reklamverenlerin bir kullanıcının cihazını benzersiz biçimde tanımlamak için kullanabileceği benzersiz kod. | | **ip_address** | Cihaz IP'si (IPv4 veya IPv6 olabilir; mevcut olduğunda IPv4 tercih edilir). Cihazın IP'si her değiştiğinde güncellenir. | | **cancellation_reason** | <p>Kullanıcının aboneliği iptal etme nedeni.</p><p></p><p>Şunlar olabilir:</p><p>**iOS & Android** _voluntarily_cancelled_, _billing_error_, _refund_</p><p>**iOS** _price_increase_, _product_was_not_available_, _unknown_, _upgraded_</p><p>**Android** _new_subscription_replace_, _cancelled_by_developer_</p> | | **android_app_set_id** | Parasal olmayan reklam kullanım senaryoları için cihaz başına, geliştirici hesabı başına ve kullanıcı tarafından sıfırlanabilir benzersiz bir ID olan [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId). | | **android_id** | Android 8.0 (API düzeyi 26) ve üzeri sürümlerde, uygulama imzalama anahtarı, kullanıcı ve cihaz kombinasyonuna özgü 64 bit'lik (onaltılık dize olarak ifade edilen) benzersiz bir sayı. Daha fazla ayrıntı için [Android geliştirici belgelerine](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) bakın. | | **device** | Son kullanıcıya görünen cihaz modeli adı. | | **currency** | İşlemin 3 harfli para birimi kodu (ISO-4217). | | **store_country** | Apple/Google mağazası tarafından belirlenen profil ülkesi. | | **attribution_source** | Attribution kaynağı. | | **attribution_network_user_id** | Attribution kaynağı tarafından kullanıcıya atanan ID. | | **attribution_status** | organic, non_organic veya unknown olabilir. | | **attribution_channel** | Pazarlama kanalı adı. | | **attribution_campaign** | Pazarlama kampanyası adı. | | **attribution_ad_group** | Attribution reklam grubu. | | **attribution_ad_set** | Attribution reklam seti. | | **attribution_creative** | Attribution kreatif anahtar kelimesi. | | **attributes** | [Özel kullanıcı nitelikleri](setting-user-attributes#custom-user-attributes) içeren JSON. Mobil uygulamanızdan göndermek üzere ayarladığınız özel nitelikleri içerir. Göndermek için [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasındaki **Send User Attributes** seçeneğini etkinleştirin. | | **integration_ids** | Bir profille ilişkili tüm entegrasyon ID'leri. Sözlük. Örnek: {'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | Here is the table structure for the paywall visits: | Sütun | Açıklama | | :-------------------- | :-------------------------------------------------------------------------------------------------------------------- | | **profile_id** | Adapty kullanıcı ID'si. | | **customer_user_id** | Geliştirici kullanıcı ID'si. Örneğin kullanıcı UUID'niz, e-postanız veya başka bir ID olabilir. Ayarlamadıysanız null. | | **profile_country** | Apple/Google store tarafından belirlenen profil ülkesi. | | **install_date** | Kurulumun gerçekleştiği ISO 8601 tarih değeri. | | **store** | _app_store_ veya _play_store_ olabilir. | | **paywall_showed_at** | Paywallın kullanıcıya gösterildiği tarih. | | **developer_id** | İşlemin gerçekleştiği paywallın geliştirici (SDK) ID'si. | | **ab_test_name** | İşlemin gerçekleştiği A/B testinin adı. | | **ab_test_revision** | İşlemin gerçekleştiği A/B testinin revizyonu. | | **paywall_name** | İşlemin gerçekleştiği paywallın adı. | | **paywall_revision** | İşlemin gerçekleştiği paywallın revizyonu. | ## Etkinlikler ve etiketler \{#events-and-tags\} İntegrasyon tarafından iletilen verileri yönetebilirsiniz. İntegrasyon aşağıdaki yapılandırma seçeneklerini sunar: | Ayar | Açıklama | | :--------------------------------- | :----------------------------------------------------------- | | **Exclude Historical Events** | Adapty SDK'nın yüklendiği günden önce gerçekleşen etkinlikleri dışarıda bırakmak için bu seçeneği işaretleyin. Bu sayede etkinlik tekrarının önüne geçilir ve raporlama doğruluğu korunur. Örneğin, bir kullanıcı 10 Ocak'ta aylık abonelik başlattıysa ve uygulamayı Adapty SDK ile 6 Mart'ta güncelledi ise Adapty, 6 Mart öncesindeki etkinlikleri atlar ve sonraki etkinlikleri saklar. | | **Include events without profile** | Adapty'de bir kullanıcı profiline bağlı olmayan işlemleri dahil etmek için bu seçeneği işaretleyin. Bunlar; Adapty SDK yüklenmeden önce yapılan satın almalar ya da mağaza sunucu bildirimlerinden gelen ve belirli bir kullanıcıyla hemen ilişkilendirilemeyen işlemler olabilir. | | **Send User Attributes** | Dil tercihleri gibi kullanıcıya özgü öznitelikleri göndermek istiyorsanız ve OneSignal planınız 10'dan fazla etiketi destekliyorsa bu seçeneği etkinleştirin. Etkinleştirildiğinde varsayılan 10 etiketin ötesinde ek bilgiler gönderilebilir. Etiket sınırının aşılması hatalara yol açabileceğini unutmayın. | Entegrasyon ayarlarının altında, Adapty'den Amazon S3'e aktarıp depolayabileceğiniz üç grup etkinlik bulunur. İhtiyacınız olanları açmanız yeterli. Adapty'nin sunduğu etkinliklerin tam listesine [buradan](events) ulaşabilirsiniz. <img src="/assets/shared/img/fd5ccb9-CleanShot_2023-08-17_at_14.49.282x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: google-cloud-storage --- --- title: "Google Cloud Storage" description: "Güvenli veri depolama için Google Cloud Storage'ı Adapty ile entegre edin." --- Google Cloud Storage entegrasyonunu etkinleştirerek [abonelik olaylarını](events) ve [paywall ziyaret verilerini](paywall-metrics) tek bir merkezi konumda güvenle saklayın: Google Cloud Storage bucket'ınız. Her gün UTC 04:00'te Adapty, bir önceki günün verilerini içeren .csv dosyalarını bucket'larınıza yükler. **event** verilerini, **paywall visit** verilerini veya **her ikisini** almak isteyip istemediğinizi seçebilirsiniz. Bu verileri istediğiniz zaman, istediğiniz zaman aralığı için [manuel olarak](#manual-data-export) da dışa aktarabilirsiniz. Entegrasyonu kurmak için Google Cloud konsolunuzda [bir bucket erişim anahtarı oluşturun](#create-google-cloud-storage-credentials) ve [bunu Adapty ayarlarınıza ekleyin](#set-up-google-cloud-storage-integration). ## Yükleme zamanlaması ve süresi \{#upload-schedule-and-duration\} Adapty, verileri her 24 saatte bir UTC 04:00'de Google Cloud Storage'a yükler. Dosyalar, bir önceki takvim gününde (UTC) oluşturulan etkinliklerin verilerini içerir. 8 Mart'ta yüklenen dosya, 7 Mart'ta 00:00:00 ile 23:59:59 UTC arasında oluşturulan tüm etkinlikleri içerir. Kuyruktaki toplam dosya sayısına ve kişisel olarak talep ettiğiniz veri miktarına bağlı olarak işlem birkaç saate kadar sürebilir. Adapty ilk yüklemede geçmiş verileri de ekliyorsa, sonraki günlük yüklemelerden daha uzun sürer. ## Google Cloud Storage entegrasyonunu kurma \{#set-up-google-cloud-storage-integration\} **Yazma erişimine** sahip geçerli bir Google Cloud hizmet hesabı anahtarına ihtiyacınız var. Oluşturmak için [kimlik bilgileri oluşturma](#create-google-cloud-storage-credentials) bölümündeki adımları izleyin. :::warning Etkinlikler ve paywall ziyaretleri için farklı kimlik bilgileriyle farklı bucket'lar kullanabilirsiniz. Ancak kimlik bilgilerinden **herhangi biri** geçersizse [**her iki yükleme de başarısız olur**](#troubleshooting). ::: [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/integrations/google-cloud-storage) sayfasına gidin ve ilgili sekmeyi açın (**Events** veya **Paywall visits**). Entegrasyonu etkinleştirin. **Google Cloud hizmet hesabı anahtarınızı** içeren dosyayı yükleyin. Hedef **bucket** ve **klasörü** belirtin. Değişikliklerinizi kaydedin. ### Etkinlik verileri için isteğe bağlı ayarlar \{#optional-settings-for-event-data\} Rapora dahil edilecek etkinlikleri belirleyebilir ve etkinlikler için özel isimler ayarlayabilirsiniz. Mevcut etkinliklerin tam listesi için [etkinlikler](events) makalesine bakın. | Ad | Varsayılan | Açıklama | | ------------------------------ | ----------------- | ----------- | | Exclude historical events | true | Adapty SDK'yı uygulamanıza entegre etmeden önce gerçekleşen etkinliklere ait bilgileri hariç tutar. <br /> <br />Analitik platformunuz Adapty'yi kullanmaya başlamadan **önce** abonelik etkinlikleri aldıysa bu seçenek yinelenen etkinliklerin gönderilmesini engeller. <Details summary="Pratik örnek"><p>Bir kullanıcı 10 Ocak'ta aylık abonelik satın aldı. Uygulamanızın 1 Mart güncellemesi Adapty SDK'yı ilk kez içeriyordu. <br /> <br /> Bu ayar **açıksa** rapor, Ocak'taki "abonelik başladı" etkinliğini veya Şubat'taki "abonelik yenilendi" etkinliğini içermez. Mart'ın 10'undaki "abonelik yenilendi" etkinliğini **içerir**.</p> </Details> | | Include events without profile | false | Bir kullanıcı profiliyle ilişkilendirilmemiş veya belirli bir kullanıcıya hemen atanamayan işlemleri dahil eder. Bunlar, Adapty SDK kurulmadan önce yapılan satın almalar veya sunucu bildirimleri aracılığıyla alınan işlemler olabilir. | | Send user attributes | false | [Özel kullanıcı özniteliklerini](setting-user-attributes) (kullanıcı verileri ve uygulama kullanım verileri gibi) dahil eder. OneSignal planınız 10'dan fazla etiketi destekliyorsa bu seçeneği seçin. Etiket limitinin aşılması hatalara yol açabilir. | ## Google Cloud Storage kimlik bilgileri oluşturma \{#create-google-cloud-storage-credentials\} Bu kılavuz, Google Cloud Platform Console'da gerekli kimlik bilgilerini oluşturmanıza yardımcı olur. Adapty'nin ham veri raporlarını belirlediğiniz bucket'a yükleyebilmesi için hizmet hesabı anahtarı ve ilgili bucket'a yazma erişimi gereklidir. Hizmet hesabı anahtarını sağlayarak ve bucket'a yazma erişimi vererek Adapty'nin ham veri raporlarını platformunuzdan depolama ortamınıza güvenli ve verimli bir şekilde aktarmasına izin vermiş olursunuz. :::warning Yalnızca Service Account HMAC key yetkilendirmesini desteklediğimizi unutmayın. Google Cloud Storage'a düzgün erişim sağlamak için Service Account HMAC key'inize "Storage Object Viewer", "Storage Legacy Bucket Writer" ve "Storage Object Creator" rollerinin eklenmiş olması zorunludur. ::: 1. İlk adım olarak Google Cloud hesabınızın [IAM](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) bölümüne gidin ve ilgili projeyi seçin ya da yeni bir proje oluşturun. 2. Ardından "+ CREATE SERVICE ACCOUNT" düğmesine tıklayarak Adapty için yeni bir hizmet hesabı oluşturun. 3. İlk adımdaki alanları doldurun; erişim izinleri sonraki aşamada verilecektir. Bu sayfa hakkında daha fazla bilgi için [belgeleri](https://docs.cloud.google.com/iam/docs/service-accounts-create) okuyabilirsiniz. 4. [Özel JSON anahtarı](https://docs.cloud.google.com/iam/docs/keys-create-delete) oluşturmak ve indirmek için KEYS bölümüne gidin ve "ADD KEY" düğmesine tıklayın. 5. DETAILS bölümünde yeni oluşturulan hizmet hesabıyla ilişkili E-posta değerini bulun ve kopyalayın. Bu bilgi, hesabı yetkilendirmek ve bucket'a yazma izni vermek için sonraki adımlarda gerekli olacaktır. 6. Google Cloud Storage'ın [Buckets](https://console.cloud.google.com/storage/browser) sayfasına gidin, mevcut bir bucket'ı seçin veya Adapty'den gelen Etkinlik ya da Ziyaret Verisi raporlarını depolamak için yeni bir bucket oluşturun. Ardından PERMISSIONS bölümüne gidin ve [GRANT ACCESS](https://docs.cloud.google.com/identity/docs/how-to?hl=en) seçeneğini tıklayın. 7. PERMISSIONS bölümüne beşinci adımda aldığınız hizmet hesabının e-posta adresini girin, Storage Object Creator rolünü seçin ve değişiklikleri uygulamak için SAVE'e tıklayın. Bucket adını ileride kullanmak üzere not edin. ## Manuel veri dışa aktarma \{#manual-data-export\} Adapty, Google Cloud Storage'a otomatik etkinlik verisi dışa aktarmanın yanı sıra manuel dosya dışa aktarma işlevi de sunar. Bu özellikle etkinlik verileri için belirli bir zaman aralığı seçebilir ve GCS bucket'ınıza manuel olarak aktarabilirsiniz. Bu sayede hangi verileri ne zaman dışa aktaracağınız üzerinde daha fazla kontrol sahibi olursunuz. Belirtilen tarih aralığı, A Tarihi 00:00:00 UTC'den B Tarihi 23:59:59 UTC'ye kadar oluşturulan etkinlikleri dışa aktarmak için kullanılır. ## Veri yapısı \{#data-structure\} Adapty, verileri tablo formatında dışa aktarmak için `.csv` dosyaları kullanır. :::warning Etkinlik içeriği zaman içinde büyüyebilir; bizim veya birlikte çalıştığımız üçüncü tarafların eklediği yeni verilerle genişleyebilir. İşleyen kodunuzun yeterince esnek olduğundan ve yapının tamamına değil belirli alanlara dayandığından emin olun. ::: ### Etkinlikler \{#events\} Raporlarınıza dahil edilen etkinlik listesini [değiştirebilirsiniz](#optional-settings-for-event-data). :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: | Sütun | Açıklama | |------|-----------| | **profile_id** | Adapty kullanıcı kimliği. | | **event_type** | Küçük harfli etkinlik adı. Etkinlik türlerini öğrenmek için [Etkinlikler](events) bölümüne bakın. | | **event_datetime** | ISO 8601 tarih formatı. | | **transaction_id** | Satın alma veya yenileme gibi bir işlem için benzersiz tanımlayıcı. | | **original_transaction_id** | Orijinal satın almanın işlem tanımlayıcısı. | | **subscription_expires_at** | Aboneliğin sona erme tarihi. Genellikle gelecektedir. | | **environment** | Sandbox veya Production olabilir. | | **revenue_usd** | USD cinsinden gelir. Boş olabilir. | | **proceeds_usd** | USD cinsinden net hasılat. Boş olabilir. | | **net_revenue_usd** | USD cinsinden net gelir (vergiler sonrası). Boş olabilir. | | **tax_amount_usd** | USD cinsinden kesilen vergi tutarı. Boş olabilir. | | **revenue_local** | Yerel para biriminde gelir. Boş olabilir. | | **proceeds_local** | Yerel para biriminde net hasılat. Boş olabilir. | | **net_revenue_local** | Yerel para biriminde net gelir (vergiler sonrası). Boş olabilir. | | **tax_amount_local** | Yerel para biriminde kesilen vergi tutarı. Boş olabilir. | | **customer_user_id** | Geliştirici kullanıcı kimliği. Örneğin kullanıcı UUID'niz, e-postanız veya başka bir kimlik olabilir. Ayarlanmadıysa null. | | **store** | *app_store* veya *play_store* olabilir. | | **product_id** | Apple App Store, Google Play Store veya Stripe'taki ürün kimliği. | | **base_plan_id** | Google Play Store'daki [Base plan ID](https://support.google.com/googleplay/android-developer/answer/12154973) veya Stripe'taki [fiyat kimliği](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices). | | **developer_id** | İşlemin gerçekleştiği paywallın geliştirici (SDK) kimliği. | | **ab_test_name** | İşlemin gerçekleştiği A/B testinin adı. | | **ab_test_revision** | İşlemin gerçekleştiği A/B testinin revizyonu. | | **paywall_name** | İşlemin gerçekleştiği paywallın adı. | | **paywall_revision** | İşlemin gerçekleştiği paywallın revizyonu. | | **profile_country** | Adapty tarafından IP'ye göre belirlenen profil ülkesi. | | **install_date** | Kurulumun gerçekleştiği ISO 8601 tarih formatı. | | **idfv** | iOS cihazlarda [identifierForVendor](https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor) | | **idfa** | iOS cihazlarda [advertisingIdentifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier) | | **advertising_id** | Android İşletim Sistemi tarafından atanan ve reklamcıların bir kullanıcının cihazını benzersiz şekilde tanımlamak için kullanabileceği benzersiz kod | | **ip_address** | Cihaz IP'si (IPv4 veya IPv6 olabilir, mevcut olduğunda IPv4 tercih edilir). Cihazın IP'si her değiştiğinde güncellenir. | | **cancellation_reason** | <p>Kullanıcının aboneliği iptal etme nedeni.</p><p></p><p>Olası değerler:</p><p>**iOS & Android** — *voluntarily_cancelled*, *billing_error*, *refund*</p><p>**Yalnızca iOS** — *price_increase*, *product_was_not_available*, *unknown*, *upgraded*</p><p>**Yalnızca Android** — *new_subscription_replace*, *cancelled_by_developer*</p> | | **android_app_set_id** | Parasal olmayan reklam kullanım durumları için cihaz başına, geliştirici hesabı başına kullanıcı tarafından sıfırlanabilir benzersiz bir kimlik olan [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId). | | **android_id** | Android 8.0 (API seviyesi 26) ve üzeri platformlarda uygulama imzalama anahtarı, kullanıcı ve cihaz kombinasyonuna özgü 64 bitlik bir sayı (onaltılık dize olarak ifade edilir). Daha fazla bilgi için [Android geliştirici belgelerine](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) bakın. | | **device** | Son kullanıcıya görünür cihaz model adı. | | **currency** | İşlemin 3 harfli para birimi kodu (ISO-4217). | | **store_country** | Apple/Google mağazası tarafından belirlenen profil ülkesi. | | **attribution_source** | Attribution kaynağı. | | **attribution_network_user_id** | Attribution kaynağı tarafından kullanıcıya atanan kimlik. | | **attribution_status** | organic, non_organic veya unknown olabilir. | | **attribution_channel** | Pazarlama kanalı adı. | | **attribution_campaign** | Pazarlama kampanyası adı. | | **attribution_ad_group** | Attribution reklam grubu. | | **attribution_ad_set** | Attribution reklam seti. | | **attribution_creative** | Attribution kreatif anahtar kelimesi. | | **attributes** | [Özel kullanıcı özniteliklerinin](setting-user-attributes#custom-user-attributes) JSON'ı. Mobil uygulamanızdan gönderecek şekilde ayarladığınız tüm özel öznitelikleri içerir. Göndermek için [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasındaki **Send User Attributes** seçeneğini etkinleştirin. | | **integration_ids** | Bir profille ilişkili tüm entegrasyon kimlikleri. Sözlük. Örnek: {'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | ### Paywall ziyaretleri \{#paywall-visits\} | Sütun | Açıklama | | :-------------------- | :----------------------------------------------------------------------------------------------------------- | | **profile_id** | Adapty kullanıcı kimliği. | | **customer_user_id** | Geliştirici kullanıcı kimliği. Örneğin kullanıcı UUID'niz, e-postanız veya başka bir kimlik olabilir. Ayarlanmadıysa null. | | **profile_country** | Apple/Google mağazası tarafından belirlenen profil ülkesi. | | **install_date** | Kurulumun gerçekleştiği ISO 8601 tarih formatı. | | **store** | *app_store* veya *play_store* olabilir. | | **paywall_showed_at** | Paywallın müşteriye gösterildiği tarih. | | **developer_id** | İşlemin gerçekleştiği paywallın geliştirici (SDK) kimliği. | | **ab_test_name** | İşlemin gerçekleştiği A/B testinin adı. | | **ab_test_revision** | İşlemin gerçekleştiği A/B testinin revizyonu. | | **paywall_name** | İşlemin gerçekleştiği paywallın adı. | | **paywall_revision** | İşlemin gerçekleştiği paywallın revizyonu. | ## Sorun giderme \{#troubleshooting\} Adapty, yükleme başlamadan **önce** erişim anahtarlarınızın geçerliliğini kontrol eder. Google Cloud Storage anahtarlarınızdan yalnızca biri geçersizse bile Adapty **yüklemeyi iptal eder** ve hata fırlatır. Yüklemelerin kesintisiz devam etmesi için anahtarlarınızı süresi dolmadan önce yenileyin. **Etkinlikler** için anahtarı güncellediyseniz **paywall ziyaretleri** için de güncellemeyi unutmayın; ya da tam tersi. --- # File: webhook-event-types-and-fields --- --- title: "Webhook olay türleri ve alanları" description: "" --- Adapty, abonelik olaylarına yanıt olarak webhook'lar gönderir. Bu bölüm, bu olay türlerini ve her webhook'ta yer alan verileri tanımlar. ## Webhook olay türleri \{#webhook-event-types\} Tüm olay türlerini webhook'unuza gönderebilir ya da yalnızca bir kısmını seçebilirsiniz. Hangi tür verilerin geleceğini ve bunların etrafında iş mantığınızı nasıl oluşturacağınızı öğrenmek için [Event flows](event-flows) sayfamıza göz atabilirsiniz. İhtiyaç duymadığınız olay türlerini, [Webhook entegrasyonunu kurma](set-up-webhook-integration#configure-webhook-integration-in-the-adapty-dashboard) adımında devre dışı bırakabilirsiniz. Aynı yerden, gerekirse Adapty'nin varsayılan olay kimliklerini kendi olay kimliklerinizle de değiştirebilirsiniz. | Event name | Description | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | subscription_started | Kullanıcı deneme süresi olmaksızın ücretli bir abonelik etkinleştirdiğinde, yani anında ücretlendirildiğinde tetiklenir. | | subscription_renewed | Abonelik yenilendiğinde ve kullanıcı ücretlendirildiğinde gerçekleşir. Bu olay, deneme süreli veya deneme süresiz aboneliklerde ikinci ödemeden itibaren başlar. | | subscription_renewal_cancelled | Kullanıcı abonelik otomatik yenilemesini kapattığında tetiklenir. Kullanıcı, ücretli abonelik süresi sonuna kadar premium özelliklere erişmeye devam eder. | | subscription_renewal_reactivated | Kullanıcı abonelik otomatik yenilemesini yeniden etkinleştirdiğinde tetiklenir. | | subscription_expired | İptal edilen bir abonelik tamamen sona erdiğinde tetiklenir. Örneğin, kullanıcı aboneliğini 12 Aralık'ta iptal etmiş ancak abonelik 31 Aralık'a kadar aktif kalmaya devam ediyorsa, olay aboneliğin sona erdiği 31 Aralık'ta kaydedilir. | | subscription_paused | Kullanıcı [abonelik duraklatma](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause) özelliğini etkinleştirdiğinde gerçekleşir (yalnızca Android). | | subscription_deferred | Abonelik satın alımı [ertelendiğinde](https://adapty.io/glossary/subscription-purchase-deferral/) tetiklenir; kullanıcılar premium özelliklere erişimlerini sürdürürken ödemeyi geciktirebilir. Bu özellik Google Play Developer API aracılığıyla kullanılabilir ve ücretsiz denemeler için ya da mali güçlük yaşayan kullanıcılara destek sağlamak amacıyla kullanılabilir. | | non_subscription_purchase | Süresiz erişim veya oyun içi coin gibi consumable ürünler dahil, abonelik dışındaki tüm satın almalar. | | trial_started | Kullanıcı deneme aboneliği etkinleştirdiğinde tetiklenir. | | trial_converted | Deneme süresi sona erdiğinde ve kullanıcı ücretlendirildiğinde (ilk satın alma) gerçekleşir. Örneğin, kullanıcının denemesi 14 Ocak'a kadar sürüyor ancak 7 Ocak'ta ücretlendiriliyorsa, bu olay 7 Ocak'ta kaydedilir. | | trial_renewal_cancelled | Kullanıcı deneme süresi boyunca abonelik otomatik yenilemesini kapattığında tetiklenir. Kullanıcı deneme süresi sonuna kadar premium özelliklere erişmeye devam eder; ancak ücretlendirilmez ve abonelik başlatılmaz. | | trial_renewal_reactivated | Kullanıcı deneme süresi boyunca abonelik otomatik yenilemesini yeniden etkinleştirdiğinde gerçekleşir. | | trial_expired | Deneme süresi aboneliğe dönüşmeden sona erdiğinde tetiklenir. | | entered_grace_period | Ödeme girişimi başarısız olduğunda ve kullanıcı ek süreye girdiğinde gerçekleşir (etkinleştirilmişse). Kullanıcı bu süre boyunca premium erişimini korur. | | billing_issue_detected | Ücretlendirme girişimi sırasında bir ödeme sorunu oluştuğunda (örn. yetersiz kart bakiyesi) tetiklenir. | | subscription_refunded | Bir abonelik iade edildiğinde (örn. Apple Support tarafından) tetiklenir. | | non_subscription_purchase_refunded | Abonelik dışı bir satın alma iade edildiğinde tetiklenir. | | access_level_updated | Kullanıcının access level'ı güncellendiğinde gerçekleşir. | :::note `subscription_renewal_reactivated` olayı, kullanıcının aboneliği iptal ettiği sırada aktif olan **önceki** ürün kimliğini taşır; kullanıcı daha sonra farklı bir ürün satın alarak aboneliği yeniden etkinleştirmiş olsa bile bu böyledir. Apple, iptal → yeniden etkinleştirme zinciri boyunca aynı `original_transaction_id`'yi kullandığından bu olay orijinal ürünü yansıtır. Yeni ürün, yeni ürüne ait faturalandırma başladığında gerçekleşen bir sonraki `subscription_renewed` olayında görünür. ::: ## Webhook etkinlik yapısı \{#webhook-event-structure\} Adapty, yalnızca [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasının **Events names** bölümünde seçtiğiniz etkinlikleri size gönderir. Webhook olayları JSON formatında serileştirilir. Sunucunuza gönderilen `POST` isteğinin gövdesi, aşağıdaki yapıya sarmalanmış serileştirilmiş olayı içerir. Tüm olaylar aynı yapıyı izler, ancak alanlar olay türüne, mağazaya ve özel yapılandırmanıza göre farklılık gösterir. Kullanıcı özellikleri, ayarladığınız [özel kullanıcı özellikleri](setting-user-attributes#custom-user-attributes)dir, dolayısıyla yapılandırdığınız içerikleri barındırır. Attribution verisi alanları da tüm olay türleri için aynıdır; ancak attribution listesi, mobil uygulamanızda kullandığınız attribution kaynaklarına göre değişir. Aşağıda bir olay örneği görebilirsiniz: ```json title="Json" showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "idfv": "00000000-0000-0000-0000-000000000000", "idfa": "00000000-0000-0000-0000-000000000000", "advertising_id": "00000000-0000-0000-0000-000000000000", "profile_install_datetime": "2000-01-31T00:00:00.000000+0000", "user_agent": "ExampleUserAgent/1.0 (Device; OS Version) Browser/Engine", "email": "john.doe@company.com", "event_type": "subscription_started", "event_datetime": "2000-01-31T00:00:00.000000+0000", "event_properties": { "store": "play_store", "currency": "USD", "price_usd": 4.99, "profile_id": "00000000-0000-0000-0000-000000000000", "cohort_name": "All Users", "environment": "Production", "price_local": 4.99, "original_price_usd": 4.99, "original_price_local": 4.99, "discount_amount_usd": 0, "discount_amount_local": 0, "base_plan_id": "b1", "developer_id": "onboarding_placement", "ab_test_name": "onboarding_ab_test", "ab_test_revision": 1, "paywall_name": "UsedPaywall", "proceeds_usd": 4.2315, "variation_id": "00000000-0000-0000-0000-000000000000", "purchase_date": "2024-11-15T10:45:36.181000+0000", "store_country": "AR", "event_datetime": "2000-01-31T00:00:00.000000+0000", "proceeds_local": 4.2415, "tax_amount_usd": 0, "transaction_id": "0000000000000000", "net_revenue_usd": 4.2415, "profile_country": "AR", "paywall_revision": "1", "profile_event_id": "00000000-0000-0000-0000-000000000000", "tax_amount_local": 0, "net_revenue_local": 4.2415, "vendor_product_id": "onemonth_no_trial", "profile_ip_address": "10.10.1.1", "consecutive_payments": 1, "rate_after_first_year": false, "original_purchase_date": "2000-01-31T00:00:00.000000+0000", "original_transaction_id": "0000000000000000", "subscription_expires_at": "2000-01-31T00:00:00.000000+0000", "profile_has_access_level": true, "profile_total_revenue_usd": 4.99, "promotional_offer_id": null, "store_offer_category": null, "store_offer_discount_type": null }, "event_api_version": 1, "profiles_sharing_access_level": [{"profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem"}], "attributions": { "appsflyer": { "ad_set": "Keywords 1.12", "status": "non_organic", "channel": "Google Ads", "ad_group": null, "campaign": "Social media influencers - Rest of the world", "creative": null, "created_at": "2000-01-31T00:00:00.000000+0000" } }, "user_attributes": {"Favourite_color": "Violet", "Pet_name": "Fluffy"}, "integration_ids": {"firebase_app_instance_id": "val1", "branch_id": "val2", "one_signal_player_id": "val3"}, "play_store_purchase_token": { "product_id": "product_123", "purchase_token": "token_abc_123", "is_subscription": true } } ``` ### Etkinlik alanları \{#event-fields\} Etkinlik parametreleri tüm etkinlik türleri için aynıdır. | **Alan** | **Tür** | **Açıklama** | |---|---|---| | **advertising_id** | UUID | Reklam kimliği (yalnızca Android). | | **attributions** | JSON | [Attribution verisi](webhook-event-types-and-fields#attributions). [Webhook ayarları](https://app.adapty.io/integrations/customwebhook)'nda **Send Attribution** etkinleştirilmişse eklenir. | | **customer_user_id** | String | [Kullanıcıları tanımlarken](ios-quickstart-identify) uygulama kodunuzda ayarladıysanız uygulamanızdaki kullanıcı kimliği (UUID, e-posta veya başka bir kimlik). Kullanıcıları uygulama kodunda tanımlamıyorsanız ya da bu kullanıcı anonimse (oturum açmamışsa) bu alan `null` olur. | | **email** | String | Adapty SDK'daki [`updateProfile`](setting-user-attributes) metodunu kullanarak veya sunucu taraflı API aracılığıyla profil oluştururken/güncellerken ayarladıysanız kullanıcının e-postası. `email` değerini SDK veya API metoduna geçirmiyorsanız bu alan `null` olur. | | **event_api_version** | Integer | Adapty API sürümü (güncel: `1`). | | **event_datetime** | ISO 8601 | Etkinliğin gerçekleşme (iş) zamanı; örneğin bir satın alma için satın alma tarihi, sona erme için son kullanma tarihi — Adapty'nin etkinliği aldığı veya gönderdiği zaman değil. [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatı (ör. `2020-07-10T15:00:00.000000+0000`). Sıralama hakkında aşağıdaki nota bakın. | | **event_properties** | JSON | [Etkinlik özellikleri](webhook-event-types-and-fields#event-properties). | | **event_type** | String | Adapty formatındaki etkinlik adı. Tam liste için [Webhook etkinlik türleri](webhook-event-types-and-fields#webhook-event-types)'ne bakın. | | **idfa** | UUID | Reklam kimliği (yalnızca Apple). [Adapty Kontrol Paneli](https://app.adapty.io/profiles/users)'ndeki profilde **IDFA**. İzleme kısıtlamaları, çocuk modu veya gizlilik ayarları nedeniyle kullanılamıyorsa `null` olabilir. | | **idfv** | UUID | Geliştirici başına benzersiz Vendor Tanımlayıcısı (IDFV). [Adapty Kontrol Paneli](https://app.adapty.io/profiles/users)'ndeki profilde **IDFV**. | | **integration_ids** | JSON | Adapty SDK'daki `setIntegrationIdentifier` metodunu kullanarak veya sunucu taraflı API aracılığıyla profil oluştururken/güncellerken ayarladıysanız kullanıcı entegrasyon kimlikleri. Kullanılamıyorsa veya entegrasyonlar devre dışıysa `null`. | | **play_store_purchase_token** | JSON | [Play Store satın alma token'ı](webhook-event-types-and-fields#play-store-purchase-token); [Webhook ayarları](https://app.adapty.io/integrations/customwebhook)'nda **Send Play Store purchase token** etkinleştirilmişse eklenir. | | **profile_id** | UUID | Adapty'nin her profil için otomatik olarak oluşturduğu profil kimliği. Kullanıcıları tanımlamıyorsanız veya giriş öncesi satın almalara izin veriyorsanız, bir Apple/Google kimliği farklı profil kimlikleriyle ilişkilendirilebilir. Adapty'nin üst/devralınan profillerle çalışma şekli hakkında [daha fazla bilgi edinin](how-profiles-work#parent-and-inheritor-profiles). | | **profile_install_datetime** | ISO 8601 | [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatında kurulum zaman damgası (ör. `2020-07-10T15:00:00.000000+0000`). | | **profiles_sharing_access_level** | JSON | Mevcut kullanıcı profili hariç [access level'ı paylaşan](general#6-sharing-paid-access-between-user-accounts) kullanıcıların listesi. Uygulamanız için access level paylaşımı etkinleştirilmişse bu liste, aynı Apple/Google kimliğiyle kullanılmış diğer profilleri içerir.<br/>Format: <ul><li>**profile_id**: (UUID) Adapty kimliği</li><li>**customer_user_id**: (String) Sağlanmışsa Customer User ID</li></ul> | | **user_agent** | String | Cihaz tarayıcısı user-agent bilgisi. | | **user_attributes** | JSON | Kullanıcı profillerini uygulamaya özgü bilgilerle zenginleştirmek için ayarlayabileceğiniz özel veriler. Genellikle kullanıcı tercihlerini (ör. tema, dil) veya davranış bayraklarını (onboarding tamamlandı, özellik kullanımı) takip etmek için kullanılır. <br/>Anahtarların string, değerlerin ise string veya sayı olduğu anahtar-değer çiftleri şeklinde biçimlendirilir (ör. `{"Favourite_color": "Violet", "Pet_name": "Fluffy"}`). <br/>Özel nitelikleri Adapty Kontrol Paneli'nde bireysel profiller için elle, Adapty SDK'daki `updateProfile` metodunu kullanarak programatik olarak ya da profil oluştururken/güncellerken sunucu taraflı API aracılığıyla ayarlayabilirsiniz. <br/>[Webhook ayarları](https://app.adapty.io/integrations/customwebhook)'nda **Send User Attributes** etkinleştirilmişse eklenir. <p>Mobil uygulama kodundaki özel nitelik değerleri float veya string olarak ayarlanabilse de sunucu taraflı API veya geçmiş içe aktarma yoluyla alınan nitelikler farklı formatlarda gelebilir. Bu durumda boolean ve integer değerler float'a dönüştürülür.</p> | :::note `event_datetime`, bir etkinliğin abonelik yaşam döngüsünde ne zaman gerçekleştiğini yansıtır; Adapty'nin bunu ne zaman işlediğini veya ilettiğini değil. Bu nedenle, etkinlikler aynı `event_datetime` değerini paylaşabilir ya da kronolojik sıradan farklı bir sırada gelebilir. Örneğin, bir `subscription_expired` etkinliği, Adapty'nin daha önce ilettiği bir `subscription_renewal_cancelled` etkinliğinden daha erken bir `event_datetime` taşıyabilir. Etkinlikleri sıralamak için `event_datetime` değerine güvenmeyin. Bunun yerine, etkinlikleri kendi alım zamanınıza göre sıralayın ve `profile_event_id` ya da işlem kimliklerini kullanarak tekrar edenleri temizleyin. ::: ### Attributions Attribution verilerini göndermek için [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasında **Send Attribution** seçeneğini etkinleştirin. Attribution verilerini göndermeyi etkinleştirdiyseniz ve [attribution entegrasyonları](attribution-integration) kurduysanız, aşağıdaki veriler her kaynak için etkinlikle birlikte gönderilir. Aynı attribution verileri tüm etkinlik türlerine gönderilir. ```json title="Json" showLineNumbers { "attributions": { "appsflyer": { "ad_set": "sample_ad_set_123", "status": "non_organic", "channel": "sample_channel", "ad_group": "sample_ad_group_456", "campaign": "sample_ios_campaign", "creative": "sample_creative_789", "created_at": "2000-01-31T00:00:00.000000+0000", "network_user_id": "0000000000000-0000000" } } } ``` | Alan adı | Alan türü | Açıklama | | :------------------ | :------------ | :------------------------------------------------- | | **ad_set** | String | Attribution reklam seti. | | **status** | String | `organic`, `non_organic,` veya `unknown` olabilir. | | **channel** | String | Pazarlama kanalı adı. | | **ad_group** | String | Attribution reklam grubu. | | **campaign** | String | Pazarlama kampanyası adı. | | **creative** | String | Attribution yaratıcı anahtar kelimesi. | | **created_at** | ISO 8601 date | Attribution kaydının oluşturulma tarihi ve saati. | | **network_user_id** | String | Attribution kaynağının kullanıcıya atadığı ID. | ### Entegrasyon ID'leri \{#integration-ids\} Aşağıdaki entegrasyon ID'leri artık etkinliklerde kullanılmaktadır: - `adjust_device_id` - `airbridge_device_id` - `amplitude_device_id` - `amplitude_user_id` - `appmetrica_device_id` - `appmetrica_profile_id` - `appsflyer_id` - `branch_id` - `facebook_anonymous_id` - `firebase_app_instance_id` - `mixpanel_user_id` - `pushwoosh_hwid` - `one_signal_player_id` - `one_signal_subscription_id` - `tenjin_analytics_installation_id` - `posthog_distinct_user_id` ### Play Store satın alma token'ı \{#play-store-purchase-token\} Bu alan, gerektiğinde bir satın almayı yeniden doğrulamak için gereken tüm verileri içerir. Yalnızca [Webhook entegrasyon ayarları](https://app.adapty.io/integrations/customwebhook)nda **Send Play Store purchase token** seçeneği etkinleştirilmişse gönderilir. | Alan | Tür | Açıklama | | :------------------ | :------ | :----------------------------------------------------------- | | **product_id** | String | Play Store'da satın alınan ürünün benzersiz tanımlayıcısı (SKU). | | **purchase_token** | String | Google Play tarafından bu satın alma işlemini benzersiz şekilde tanımlamak için oluşturulan token. | | **is_subscription** | Boolean | Satın alınan ürünün bir abonelik (`true`) mi yoksa tek seferlik satın alma (`false`) mı olduğunu belirtir. | ### Etkinlik özellikleri \{#event-properties\} Etkinlik özellikleri, etkinlik türüne ve hatta aynı türdeki etkinlikler arasında bile farklılık gösterebilir. Örneğin, App Store'dan gelen bir etkinlik, `base_plan_id` gibi Android'e özgü özellikleri içermez. [Access Level Updated](webhook-event-types-and-fields#for-access-level-updated-event) olayının kendine özgü özellikleri bulunduğundan, bu olay için ayrı bir bölüm hazırladık. Benzer şekilde, yalnızca belirli olay türlerine özgü oldukları için [Ek vergi ve gelir olayı özellikleri](webhook-event-types-and-fields#additional-tax-and-revenue-event-properties) de ayrı bir bölümde ele alınmaktadır. #### Çoğu olay türü için \{#for-most-event-types\} **Access Level Updated** eventi dışındaki çoğu olay türü için olay özellikleri tutarlıdır (bu olay kendi bölümünde açıklanmaktadır). Aşağıda özellikleri öne çıkaran ve bunların belirli olaylara ait olup olmadığını gösteren kapsamlı bir tablo yer almaktadır. :::note Adapty, diğer para birimlerini [currencylayer.com](https://currencylayer.com/) döviz kuru üzerinden USD'ye çevirir (her 8 saatte bir güncellenir). Kur, **işlem anında sabitlenir** — sonraki değişiklikler dönüşüm sonucunu etkilemez. ::: | Alan | Tür | Açıklama | |:------------------------------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **ab_test_name** | String | İşlemin kaynaklandığı [Adapty A/B testi](ab-tests) adı. | | **ab_test_revision** | Integer | İşlemin kaynaklandığı A/B testinin revizyonu. | | **base_plan_id** | String | Google Play Store'daki [temel plan ID'si](https://support.google.com/googleplay/android-developer/answer/12154973) veya Stripe'taki [fiyat ID'si](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices). | | **cancellation_reason** | String | <p>Olası iptal nedenleri: `voluntarily_cancelled`, `billing_error`, `price_increase`, `product_was_not_available`, `refund`, `cancelled_by_developer`, `new_subscription_replace`, `upgraded`, `unknown`, `adapty_revoked`.</p><p>Şu etkinlik türlerinde bulunur:</p>`subscription_cancelled`, `subscription_refunded` ve `trial_cancelled`. | | **cohort_name** | String | Kullanıcıya hangi paywall'ın gösterileceğini belirleyen [kitlenin](audience) adı. | | **consecutive_payments** | Integer | Kullanıcının kesintisiz olarak abone olduğu dönem sayısı. Mevcut dönemi de içerir. | | **currency** | String | Yerel para birimi. | | **developer_id** | String | İşlemin kaynaklandığı [placement](placements) ID'si. | | **discount_amount_local** | Float | İşleme uygulanan indirim: Apple/Google kesintisi öncesinde standart fiyat eksi gerçekte tahsil edilen tutar, yerel para birimi cinsinden. Tam fiyatlı satın alımlarda `0`. Ücretsiz deneme süresinde hiçbir şey tahsil edilmediğinden tam standart fiyata (`original_price_local`) eşittir. Bir teklif uygulandığında ancak standart fiyat bilinmediğinde `null` (bkz. `original_price_local`). App Store ön ödemeli teklifler için her zaman `null`'dır: tek seferlik ön ödeme birden fazla faturalandırma dönemini kapsadığından dönemlik standart fiyatla karşılaştırılamaz. | | **discount_amount_usd** | Float | `discount_amount_local` değerinin USD cinsinden karşılığı. | | **environment** | String | Olası değerler: `Sandbox` veya `Production`. | | **event_datetime** | ISO 8601 date | Etkinliğin tarih ve saati. Etkinliğin kök düzeyindekiyle aynıdır. | | **original_price_local** | Float | Ürünün Apple/Google kesintisi öncesindeki standart, indirimsiz fiyatı, yerel para birimi cinsinden. Abonelikler için bu yenileme fiyatıdır. Tam fiyatlı satın alımlarda `price_local` değerine eşittir ve tek seferlik satın alımlar için her zaman `price_local` değerine eşittir; zira mağazalar bunlar için ayrı bir standart fiyat bildirmez. Mağazanın güvenilir bir standart fiyat bildirmediği indirimli satın alımlarda `null` olur (örneğin otomatik yenileme kapalıysa, yenileme hâlâ bir teklif içeriyorsa veya ürün değişikliği beklemedeyse). | | **original_price_usd** | Float | `original_price_local` ile aynı, USD cinsinden. | | **original_purchase_date** | ISO 8601 date | Yinelenen abonelikler için orijinal satın alma, zincirdeki ilk işlemdir; orijinal işlem ID'si olarak adlandırılan bu ID, yenileme zincirini birbirine bağlar; sonraki işlemler bunun uzantılarıdır. Orijinal satın alma tarihi, bu ilk işlemin tarih ve saatidir. | | **original_transaction_id** | String | <p>Yinelenen abonelikler için bu, yenileme zincirini birbirine bağlayan orijinal işlem ID'sidir. Orijinal işlem zincirdeki ilktir; sonraki işlemler bunun uzantılarıdır.</p><p>Uzantı yoksa `original_transaction_id`, store_transaction_id ile eşleşir.</p> | | **paywall_name** | String | İşlemin kaynaklandığı paywall'ın adı. | | **paywall_revision** | String | İşlemin kaynaklandığı paywall'ın revizyonu. Varsayılan değer 1'dir. | | **price_local** | Float | Apple/Google kesintisi öncesinde işlem için tahsil edilen tutar, yerel para birimi cinsinden. Ücretsiz denemeler için hiçbir şey tahsil edilmediğinden `null`'dır. | | **price_usd** | Float | Apple/Google kesintisi öncesinde işlem için tahsil edilen tutar, USD cinsinden. Ücretsiz denemeler için hiçbir şey tahsil edilmediğinden `null`'dır. | | **profile_country** | String | Adapty tarafından profil IP'sine göre belirlenir. | | **profile_event_id** | UUID | Tekilleştirme için kullanılabilecek benzersiz etkinlik ID'si. | | **profile_has_access_level** | Boolean | Profilin etkin bir access level'a sahip olup olmadığını belirten boolean değer. | | **profile_id** | UUID | Adapty tarafından oluşturulan profil ID'si. Etkinliğin kök düzeyindekiyle aynıdır. | | **profile_ip_address** | String | Profil IP'si (IPv4 veya IPv6 olabilir; mevcut olduğunda IPv4 tercih edilir). [Uygulama ayarlarında](https://app.adapty.io/settings/general) **Collect users' IP addresses** devre dışıysa `null`. | | **profile_total_revenue_usd** | Float | İadeler düşüldükten sonra profile ait toplam gelir. | | **promotional_offer_id** | String | Kullanılan [promosyon teklifinin](offers) Adapty ID'si. Bu ID'yi kontrol panelinde teklif oluştururken siz belirlersiniz. | | **purchase_date** | ISO 8601 date | Ürünün satın alındığı tarih ve saat. | | **rate_after_first_year** | Boolean | Aboneliğin bir yıllık kesintisiz yenilemenin ardından indirimli komisyon oranına (genellikle %15) hak kazanıp kazanmadığını gösteren boolean değer. Komisyon oranları programa uygunluk ve ülkeye göre değişir. Ayrıntılar için bkz. [Mağaza komisyonu ve vergiler](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue). | | **store** | String | Ürünün satın alındığı mağaza. Standart değerler: **app_store**, **play_store**, **stripe**, **paddle**. <br/>Sunucu taraflı API aracılığıyla [özel mağaza işlemleri](api-adapty/operations/setTransaction) ayarladıysanız **store** parametresindeki değer kullanılır. | | **store_country** | String | Uygulama mağazası tarafından bize gönderilen ülke. | | **store_offer_category** | String | Uygulanan teklif kategorisi. Olası değerler: `introductory`, `promotional`, `winback`. | | **store_offer_discount_type** | String | Uygulanan teklif türü. Olası değerler: `free_trial`, `pay_as_you_go` ve `pay_up_front`. | | **store_offer_number_of_periods** | Integer | Bir teklifin indirim uyguladığı temel faturalandırma dönemi sayısı (1 veya daha fazla). Yalnızca bir teklif geçerli olduğunda bulunur. App Store ön ödemeli tekliflerde ve mağazanın teklif süresini bildirmediği durumlarda `null`. | | **subscription_expires_at** | ISO 8601 date | Aboneliğin sona erme tarihi. Genellikle gelecekte bir tarihtir. | | **transaction_id** | String | Bir işlem için benzersiz tanımlayıcı. | | **trial_duration** | String | Deneme süresinin gün cinsinden uzunluğu. "{} days" biçiminde gönderilir; örneğin "7 days". Yalnızca denemeyle ilgili etkinlik türlerinde bulunur: `trial_started`, `trial_converted`, `trial_cancelled`. | | **variation_id** | UUID | Satın almanın gerçekleştiği paywall'ın benzersiz ID'si. | | **vendor_product_id** | String | <p>Apple App Store, Google Play Store veya Stripe'taki ürün ID'si.</p><p>Erişim gerçek bir mağaza işlemi olmadan sağlandıysa `vendor_product_id` şunlardan biri olacaktır:</p><ul><li>`adapty_server_side_product` — [sunucu taraflı API](api-adapty/operations/grantAccessLevel) aracılığıyla verilmiş.</li><li>`adapty_dashboard_product` — Adapty Kontrol Paneli'nde [manuel olarak verilmiş](give-access-level-to-specific-customer).</li><li>`adapty_promotion` — eski sürüm.</li></ul> | #### Ek vergi ve gelir olayı özellikleri \{#additional-tax-and-revenue-event-properties\} Aşağıdaki vergi ve gelirle ilgili olay özellikleri, yalnızca belirli olay türleri için geçerli olan ek alanlardır. Yani listelenen olay türleri, [Çoğu olay türü için olay özellikleri](webhook-event-types-and-fields#for-most-event-types) bölümündeki alanların yanı sıra aşağıda listelenen ek alanları da içerir. Vergi ve gelir olay özelliklerine sahip olay türleri: - `subscription_renewed` - `subscription_initial_purchase` (`subscription_started` olarak da bilinir — aynı olaydır) - `subscription_refunded` - `non_subscription_purchase` | Alan | Tür | Açıklama | | :-------------------- | :---- | :----------------------------------------------------------- | | **net_revenue_local** | Float | Net gelir (Apple/Google payı ve vergiler düşüldükten sonraki gelir) yerel para biriminde. | | **net_revenue_usd** | Float | Net gelir (Apple/Google payı ve vergiler düşüldükten sonraki gelir) ABD doları cinsinden. | | **proceeds_local** | Float | Apple/Google payı düşüldükten sonraki ürün fiyatı yerel para biriminde. | | **proceeds_usd** | Float | Apple/Google payı düşüldükten sonraki ürün fiyatı. | | **tax_amount_local** | Float | Kesilen vergi tutarı yerel para biriminde. | | **tax_amount_usd** | Float | Kesilen vergi tutarı ABD doları cinsinden. | #### `non_subscription_purchase` örnek payload'u `non_subscription_purchase`, abonelik etkinlikleriyle aynı yapıyı izler ancak tek seferlik veya consumable bir satın almayı yansıtır. Yalnızca aboneliğe özgü alanlar geçerli değildir: `cancellation_reason`, `will_renew`, `is_in_grace_period`, `is_refund`, `is_lifetime` ve `trial_duration` bulunmaz. `subscription_expires_at` mevcut olsa da değeri `null`'dır. Vergi ve gelir alanları (`net_revenue_*`, `proceeds_*`, `tax_amount_*`) dahil edilmiştir. <details> <summary>Örnek payload (genişletmek için tıklayın)</summary> ```json title="Json" showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "event_type": "non_subscription_purchase", "event_datetime": "2000-01-31T00:00:00.000000+0000", "event_properties": { "store": "app_store", "currency": "USD", "price_usd": 4.99, "price_local": 4.99, "original_price_usd": 4.99, "original_price_local": 4.99, "discount_amount_usd": 0, "discount_amount_local": 0, "proceeds_usd": 4.2415, "proceeds_local": 4.2415, "net_revenue_usd": 4.2415, "net_revenue_local": 4.2415, "tax_amount_usd": 0, "tax_amount_local": 0, "profile_id": "00000000-0000-0000-0000-000000000000", "environment": "Production", "vendor_product_id": "100coins", "transaction_id": "0000000000000000", "original_transaction_id": "0000000000000000", "purchase_date": "2024-11-15T10:45:36.181000+0000", "original_purchase_date": "2024-11-15T10:45:36.181000+0000", "subscription_expires_at": null, "store_country": "US", "profile_country": "US", "profile_ip_address": "10.10.1.1", "profile_has_access_level": false, "profile_total_revenue_usd": 4.99, "consecutive_payments": 1, "rate_after_first_year": false, "profile_event_id": "00000000-0000-0000-0000-000000000000" }, "event_api_version": 1 } ``` </details> #### Access Level Updated eventi için \{#for-access-level-updated-event\} **Access Level Updated** eventi, yalnızca Webhook entegrasyonu etkin olduğunda ve bu event türü etkinleştirildiğinde oluşturulan özel bir webhook eventidir. Etkinleştirilmişse, yapılandırılmış Webhook'a gönderilir ve **Event Feed**'de görünür. Etkinleştirilmemişse event oluşturulmaz. [Access level paylaşımını](general#6-sharing-paid-access-between-user-accounts) etkinleştirdiyseniz, **access level updated** eventi, access level'ı paylaşan tüm profiller için gönderilir. :::tip Bu etkinliği kullanarak veritabanınızdaki kullanıcının access level'ını güncelleyebilir, backend'inizde premium özellikleri etkinleştirip devre dışı bırakabilir ve erişimi cihazlar veya platformlar arasında senkronize tutabilirsiniz. ::: | Özellik | Tür | Açıklama | | ---------------------------------- | ------------- | ------------------------------------------------------------ | | **ab_test_name** | String | İşlemin gerçekleştiği A/B testinin adı. | | **access_level_id** | String | Access level'ın ID'si. | | **activated_at** | ISO 8601 date | Erişimin en son etkinleştirildiği tarih ve saat. | | **active_introductory_offer_type** | String | Uygulanan başlangıç teklifinin türü. Olası değerler: `free_trial`, `pay_as_you_go` ve `pay_up_front`. | | **active_promotional_offer_id** | String | Adapty Kontrol Paneli'nin Ürün bölümünde belirtilen promosyon teklifinin ID'si. | | **active_promotional_offer_type** | String | Uygulanan promosyon teklifinin türü. Olası değerler: `free_trial`, `pay_as_you_go` ve `pay_up_front`. | | **base_plan_id** | String | Google Play Store'daki [temel plan ID'si](https://support.google.com/googleplay/android-developer/answer/12154973) veya Stripe'taki [fiyat ID'si](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices). | | **billing_issue_detected_at** | ISO 8601 date | Faturalama sorununun tespit edildiği tarih ve saat. | | **cancellation_reason** | String | Olası iptal nedenleri: `voluntarily_cancelled`, `billing_error`, `price_increase`, `product_was_not_available`, `refund`, `cancelled_by_developer`, `new_subscription_replace`, `upgraded`, `unknown`, `adapty_revoked`. | | **cohort_name** | String | Profilin ait olduğu kitlenin adı. | | **currency** | String | Yerel para birimi (varsayılan olarak USD). | | **developer_id** | String | İşlemin gerçekleştiği placement'ın ID'si. | | **environment** | String | Olası değerler: `Sandbox` veya `Production`. | | **event_datetime** | ISO 8601 date | Olayın tarih ve saati. | | **expires_at** | ISO 8601 date | Erişimin sona ereceği tarih ve saat. | | **is_active** | Boolean | Access level'ın aktif olup olmadığını gösteren Boolean değer. | | **is_in_grace_period** | Boolean | Profilin ek süre içinde olup olmadığını gösteren Boolean değer. | | **is_lifetime** | Boolean | Access level'ın süresiz erişim olup olmadığını gösteren Boolean değer. | | **is_refund** | Boolean | İşlemin iade olup olmadığını gösteren Boolean değer. | | **original_purchase_date** | ISO 8601 date | Yenilenen abonelikler için orijinal satın alma, zincirdeki ilk işlemdir; original transaction ID adı verilen ID'si yenileme zincirini birbirine bağlar; sonraki işlemler bunun uzantısıdır. Orijinal satın alma tarihi, bu ilk işlemin tarih ve saatidir. | | **original_transaction_id** | String | <p>Yenilenen abonelikler için bu, yenileme zincirini birbirine bağlayan orijinal işlem ID'sidir. Orijinal işlem zincirdeki ilkidir; sonraki işlemler bunun uzantısıdır.</p><p>Uzantı yoksa `original_transaction_id`, store_transaction_id ile aynıdır.</p>Orijinal satın almanın işlem tanımlayıcısı. | | **paywall_name** | String | İşlemin gerçekleştiği paywall'un adı. | | **paywall_revision** | String | İşlemin gerçekleştiği paywall'un revizyonu. Varsayılan değer 1'dir. | | **profile_country** | String | Adapty tarafından profil IP'sine göre belirlenir. | | **profile_event_id** | UUID | Tekilleştirme için kullanılabilecek benzersiz olay ID'si. | | **profile_has_access_level** | Boolean | Profilin aktif bir access level'a sahip olup olmadığını gösteren Boolean değer. | | **profile_id** | UUID | Adapty dahili kullanıcı profili ID'si. | | **profile_ip_address** | String | Profil IP'si (IPv4 veya IPv6 olabilir; mevcut olduğunda IPv4 tercih edilir). [Uygulama ayarlarında](https://app.adapty.io/settings/general) **Collect users' IP addresses** devre dışıysa `null`. | | **profile_total_revenue_usd** | Float | Profil için iadeler dahil toplam gelir. | | **purchase_date** | ISO 8601 date | Ürünün satın alındığı tarih ve saat. | | **renewed_at** | ISO 8601 date | Erişimin yenileneceği tarih ve saat. | | **starts_at** | ISO 8601 date | Access level'ın başladığı tarih ve saat. | | **store** | String | Ürünün satın alındığı mağaza. Standart değerler: **app_store**, **play_store**, **stripe**, **paddle**. <br/>Sunucu tarafı API'sini kullanarak [özel mağaza işlemleri](api-adapty/operations/setTransaction) ayarladıysanız **store** parametresindeki değer kullanılır. | | **store_country** | String | Uygulama mağazası tarafından Adapty'ye gönderilen ülke. | | **subscription_expires_at** | ISO 8601 date | Aboneliğin sona erme tarihi. | | **transaction_id** | String | Bir işlem için benzersiz tanımlayıcı. | | **trial_duration** | String | Deneme süresinin gün cinsinden uzunluğu (ör. "7 days"). | | **variation_id** | UUID | Satın almaları bu paywall'a atfetmek için kullanılan varyant tanımlayıcısı. | | **vendor_product_id** | String | <p>Mağazadaki (Apple/Google/Stripe) ürün ID'si.</p><p>Gerçek bir mağaza işlemi olmadan erişim sağlandıysa `vendor_product_id` şunlardan biri olur:</p><ul><li>`adapty_server_side_product` — [sunucu tarafı API'si](api-adapty/operations/grantAccessLevel) aracılığıyla sağlandı.</li><li>`adapty_dashboard_product` — Adapty Kontrol Paneli'nde [manuel olarak sağlandı](give-access-level-to-specific-customer).</li><li>`adapty_promotion` — eski sürüm.</li></ul> | | **will_renew** | Boolean | Ücretli access level'ın yenilenip yenilenmeyeceğini gösterir. | :::warning Bu yapının zamanla büyüyebileceğini unutmayın — biz veya birlikte çalıştığımız üçüncü taraflar tarafından yeni veriler eklenebilir. Bu yapıyı işleyen kodunuzun yeterince sağlam olduğundan ve tüm yapıya değil, belirli alanlara dayandığından emin olun. ::: --- # File: set-up-webhook-integration --- --- title: "Webhook entegrasyonunu kurma" description: "Olay takibini otomatikleştirmek için Adapty'de webhook entegrasyonunu kurun." --- Adapty [webhook entegrasyonu](webhook) şu adımlardan oluşur: <img src="/assets/shared/img/webhook-setup.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> 1. **Endpoint'inizi kurarsınız:** 1. Sunucunuzun **Content-Type** başlığı `application/json` olarak ayarlanmış Adapty isteklerini işleyebildiğinden emin olun. 2. Sunucunuzu Adapty'nin doğrulama isteğini alacak ve herhangi bir `2xx` durum koduyla JSON gövdesiyle yanıt verecek şekilde yapılandırın. 3. Bağlantı doğrulandıktan sonra [abonelik olaylarını](#subscription-events) işleyin. 2. **Webhook entegrasyonunu yapılandırıp etkinleştirirsiniz** [Adapty Kontrol Paneli](#configure-webhook-integration-in-the-adapty-dashboard)'nden. Ayrıca [Adapty olaylarını özel olay adlarıyla eşleştirebilirsiniz](#configure-webhook-integration-in-the-adapty-dashboard). Üretime geçmeden önce **Sandbox ortamında** test etmenizi öneririz. 3. **Adapty sunucunuza bir doğrulama isteği gönderir.** 4. **Sunucunuz** `2XX` durum kodu ve JSON gövdesiyle yanıt verir. 5. **Adapty geçerli bir yanıt aldığında abonelik olaylarını göndermeye başlar.** ## Adapty isteklerini işlemek için sunucunuzu kurma \{#set-up-your-server-to-process-adapty-requests\} Adapty, webhook endpoint'inize 2 tür istek gönderir: 1. [Doğrulama isteği](#verification-request): Bağlantının doğru kurulduğunu doğrulamak için gönderilen ilk istek. Bu istek herhangi bir olay içermez ve Adapty Kontrol Paneli'nin Webhook entegrasyonunda **Save** düğmesine tıkladığınız anda gönderilir. Endpoint'inizin doğrulama isteğini başarıyla aldığını onaylamak için doğrulama yanıtıyla cevap vermeniz gerekir. 2. [Abonelik olayı](#subscription-events): Adapty sunucusunun bir olay oluşturulduğunda gönderdiği standart istek. Sunucunuzun belirli bir yanıt vermesi gerekmez; Adapty sunucusunun ihtiyacı olan tek şey, mesajı başarıyla alması durumunda standart 200 kodlu bir HTTP yanıtıdır. ### Doğrulama isteği \{#verification-request\} Adapty Kontrol Paneli'nde webhook entegrasyonunu etkinleştirdikten sonra Adapty, gövde olarak boş bir JSON nesnesi `{}` içeren bir POST doğrulama isteği gönderir. Endpoint'inizin **Content-Type header**'ını `application/json` olarak ayarlayın; yani sunucunuzun endpoint'i, gelen webhook isteğinin yükünün JSON formatında olmasını beklemelidir. Sunucunuz 2xx durum koduyla yanıt vermeli ve örneğin şu şekilde geçerli bir JSON yanıtı göndermelidir: ```json title="Json" {} ``` Adapty doğrulama yanıtını doğru formatta ve 2xx durum koduyla aldığında, Adapty webhook entegrasyonunuz tam olarak yapılandırılmış olur. ### Abonelik olayları \{#subscription-events\} Abonelik olayları, **Content-Type** başlığı `application/json` olarak ayarlanmış şekilde gönderilir ve JSON formatında olay verisi içerir. Olası olay türleri ve istek yapıları için [Webhook olay türleri ve alanları](webhook-event-types-and-fields) sayfasına bakın. ## Adapty Kontrol Paneli'nde webhook entegrasyonunu yapılandırma \{#configure-webhook-integration-in-the-adapty-dashboard\} Adapty'de, Apple veya Stripe sandbox ortamından ya da Google test hesabından gelen test olayları ile üretim olayları için ayrı akışlar yapılandırabilirsiniz. :::tip Adapty, her ortam (production ve sandbox) için tek bir webhook URL'sini destekler. Olayları birden fazla servise iletmek istiyorsanız, webhook'u kendi backend'inize yönlendirin ve oradan dağıtım yapın. ::: Üretim olayları için, geri çağrıların gönderileceği URL'yi belirten **Production endpoint URL** alanını kullanın. Ayrıca **Authorization header value for production endpoint** alanını da yapılandırın; bu başlık, sunucunuzun Adapty olaylarını doğrulaması için kullanılır. **Authorization header value for production endpoint** alanında belirtilen değerin, herhangi bir değişiklik veya ekleme yapılmadan `Authorization` başlığı olarak aynen kullanılacağını unutmayın. Test olayları için **Sandbox endpoint URL** ve **Authorization header value for sandbox endpoint** alanlarını kullanın. Webhook entegrasyonunu kurmak için: 1. Adapty Kontrol Paneli'nde [Integrations -> Webhook](https://app.adapty.io/integrations/customwebhook) sayfasını açın. <img src="/assets/shared/img/webhook_integration.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Entegrasyonu başlatmak için geçiş düğmesini açın. 4. Entegrasyon alanlarını doldurun: | Alan | Açıklama | | ------------------------------------------------------ | ------------------------------------------------------------ | | **Production endpoint URL** | Adapty'nin üretimdeki olaylar için HTTP POST istekleri göndermek üzere kullandığı URL. | | **Authorization header value for production endpoint** | <p>Sunucunuzun üretimdeki Adapty isteklerini doğrulamak için kullanacağı başlık. Bu alanda belirtilen değerin, herhangi bir değişiklik veya ekleme yapılmadan `Authorization` başlığı olarak aynen kullanılacağını unutmayın.</p><p></p><p>Zorunlu olmamakla birlikte, güvenliği artırmak için kullanılması önemle tavsiye edilir.</p> | Sandbox ortamındaki test ihtiyaçlarınız için iki ek alan daha mevcuttur: | Test alanı | Açıklama | | --------------------------------------------------- | ------------------------------------------------------------ | | **Sandbox endpoint URL** | Adapty'nin sandbox ortamındaki olaylar için HTTP POST istekleri göndermek üzere kullandığı URL. | | **Authorization header value for sandbox endpoint** | <p>Sunucunuzun sandbox ortamında test sırasında Adapty isteklerini doğrulamak için kullanacağı başlık. Bu alanda belirtilen değerin, herhangi bir değişiklik veya ekleme yapılmadan `Authorization` başlığı olarak aynen kullanılacağını unutmayın.</p><p></p><p>Zorunlu olmamakla birlikte, güvenliği artırmak için kullanılması önemle tavsiye edilir.</p> | 4. (İsteğe bağlı) Almak istediğiniz event'leri seçin ve isimlerini eşleştirin. Farklı durumlarda hangi event'lerin tetiklendiğini görmek için [Event akışları](event-flows) sayfasına bakın. Event ID'leriniz Adapty'de kullanılanlardan farklıysa, kendi sisteminizdeki ID'leri olduğu gibi bırakın ve [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasının **Events names** bölümündeki varsayılan Adapty event ID'lerini sizinkilerle değiştirin. Etkinlik ID'si herhangi bir string olabilir; yalnızca webhook işleme sunucunuzdaki etkinlik ID'sinin Adapty Kontrol Paneli'ne girdiğinizle eşleştiğinden emin olun. Etkinleştirilmiş etkinlikler için etkinlik ID'sini boş bırakamazsınız. <img src="/assets/shared/img/86942b8-event_names_renaming.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Ek alanlar ve seçenekler zorunlu değildir; ihtiyacınıza göre kullanın: | Ayar | Açıklama | | :--------------------------------- | :----------------------------------------------------------- | | **Send Trial Price** | Etkinleştirildiğinde, Adapty **Trial Started** olayı için `price_local` ve `price_usd` alanlarına abonelik fiyatını ekler. | | **Exclude Historical Events** | Kullanıcının Adapty SDK ile uygulamayı yüklemesinden önce gerçekleşen olayları hariç tutmayı seçin. Bu, olayların tekrarlanmasını önler ve doğru raporlamayı sağlar. Örneğin, bir kullanıcı 10 Ocak'ta aylık abonelik başlattıysa ve 6 Mart'ta Adapty SDK ile uygulamayı güncellediyse, Adapty 6 Mart öncesindeki olayları atlayıp sonraki olayları saklar. | | **Send user attributes** | Dil tercihleri gibi kullanıcıya özgü nitelikleri göndermek için bu seçeneği etkinleştirin. Bu nitelikler `user_attributes` alanında görünecektir. Daha fazla bilgi için [Olay alanları](webhook-event-types-and-fields#event-fields) bölümüne bakın. | | **Send attribution** | Attribution bilgilerini (örn. AppsFlyer verileri) `attributions` alanına eklemek için bu seçeneği açın. Ayrıntılar için [Attribution verisi](webhook-event-types-and-fields#attributions) bölümüne bakın. | | **Send Play Store purchase token** | Gerektiğinde satın alma yeniden doğrulaması için gereken Play Store token'ını almak üzere bu seçeneği açın. Etkinleştirildiğinde olaya `play_store_purchase_token` parametresi eklenir. İçeriği hakkında ayrıntılar için [Play Store purchase token](webhook-event-types-and-fields#play-store-purchase-token) bölümüne bakın. | 6. Değişiklikleri onaylamak için **Save** düğmesine tıklamayı unutmayın. **Save** düğmesine tıkladığınız anda Adapty bir doğrulama isteği gönderir ve sunucunuzun doğrulama yanıtını bekler. ### Gönderilecek olayları seçme ve olay adlarını eşleştirme \{#choose-events-to-send-and-map-event-names\} Yanındaki geçiş düğmesini etkinleştirerek sunucunuzda almak istediğiniz olayları seçin. Olay adlarınız Adapty'dekilerden farklıysa ve kendi adlarınızı korumak istiyorsanız, [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) sayfasının **Events names** bölümünde varsayılan Adapty olay adlarını kendinizinkilerle değiştirerek eşleştirme yapabilirsiniz. <img src="/assets/shared/img/86942b8-event_names_renaming.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Olay adı herhangi bir dize olabilir. Etkinleştirilmiş olaylar için alanları boş bırakamazsınız. Adapty olay adını yanlışlıkla sildiyseniz, adı her zaman [Üçüncü taraf entegrasyonlarına gönderilecek olaylar](events) konusundan kopyalayabilirsiniz. ## Webhook olaylarını işleme \{#handle-webhook-events\} Webhook'lar genellikle olay gerçekleştikten sonra 5 ila 60 saniye içinde iletilir. Ancak iptal olayları, kullanıcı aboneliğini iptal ettikten sonra teslim edilmesi 2 saate kadar sürebilir. Sunucunuzun yanıt durum kodu 200-404 aralığının dışındaysa Adapty, üstel geri çekilme (exponential backoff) yöntemiyle yeniden deneme yapar. İlk yeniden deneme, ilk başarısızlıktan yaklaşık **1 dakika** sonra gerçekleşir ve her sonraki denemede bu süre iki katına çıkar; toplamda 24 saat boyunca 9 yeniden denemeye kadar uzanır. Webhook'unuzu, yanıt vermeden önce Adapty'den gelen olay gövdesini yalnızca temel düzeyde doğrulayacak şekilde ayarlamanızı öneririz. Sunucunuz olayı işleyemiyorsa ve Adapty'nin yeniden denemesini istemiyorsanız 200-404 aralığında bir durum kodu kullanın. Ayrıca zaman alan görevleri asenkron olarak ele alın ve Adapty'ye hızlıca yanıt verin. Adapty 10 saniye içinde yanıt almazsa denemeyi başarısız sayar ve yeniden dener. --- # File: test-webhook --- --- title: "Webhook entegrasyonunu test etme" description: "Abonelik etkinliği takibini otomatikleştirmek için Adapty'de webhook entegrasyonlarını test edin." --- Entegrasyonunuzu kurduktan sonra test etme zamanı gelmiş demektir. Hem sandbox hem de production entegrasyonunuzu test edebilirsiniz. Sandbox ile başlamanızı ve üzerinde maksimum doğrulama yapmanızı öneririz: - Etkinlikler gönderiliyor ve başarıyla iletiliyor. - Geçmiş etkinlikler, **Trial started** etkinliği için abonelik fiyatı, attribution, kullanıcı öznitelikleri ve Google Play Store satın alma token'ının bir etkinlikle birlikte gönderilip gönderilmeyeceğine ilişkin seçenekleri doğru yapılandırdınız. - Etkinlik adlarını doğru eşleştirdiniz ve sunucunuz bunları işleyebiliyor. ## Nasıl test edilir \{#how-to-test\} Bir entegrasyonu test etmeye başlamadan önce aşağıdakileri tamamladığınızdan emin olun: 1. Webhook entegrasyonunu [Webhook entegrasyonunu kurma](set-up-webhook-integration) konusunda anlatıldığı şekilde yapılandırın. 2. [Apple App Store'da uygulama içi satın almaları test etme](test-purchases-in-sandbox) ve [Google Play Store'da uygulama içi satın almaları test etme](testing-on-android) konularında anlatıldığı şekilde ortamı kurun. Test uygulamanızı production ortamında değil, sandbox ortamında derlediğinizden emin olun. 3. Webhook'a göndermeyi seçtiğiniz bir etkinliği tetikleyecek bir satın alma yapın / deneme başlatın / iade isteyin. Örneğin **Subscription started** etkinliğini almak için yeni bir abonelik satın alın. ## Sonucun doğrulanması \{#validation-of-the-result\} ### Başarılı etkinlik gönderme sonucu \{#successful-sending-events-result\} Entegrasyon başarılı olduğunda, etkinlik entegrasyonun **Last sent events** bölümünde görünür ve **Success** durumunu alır. <img src="/assets/shared/img/6ccc3bb-webhook_integration_success.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Başarısız etkinlik gönderme sonucu \{#unsuccessful-sending-events-result\} | Sorun | Çözüm | |-----|--------| | Etkinlik görünmedi | Satın alma gerçekleşmediğinden etkinlik oluşturulmadı. Çözüm için [Test satın almalarında sorun giderme](troubleshooting-test-purchases) konusuna bakın. | | Etkinlik göründü ancak **Sending failed** durumunda | <p>Teslim edilebilirliği HTTP durum koduna göre belirliyoruz; **200-399 aralığı dışındaki** her şeyi başarısız olarak kabul ediyoruz.</p><p>Sorun hakkında daha fazla bilgi edinmek için aşağıda gösterildiği gibi başarısız etkinliğinizin **Sending failed** durumunun üzerine gelin.</p> | <img src="/assets/shared/img/12ff189-hover_sending_failed.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: handle-integration-errors --- --- title: "Entegrasyon hatalarını yönetme" description: "Entegrasyon hatalarını yönetme" --- Attribution, mesajlaşma veya analitik entegrasyonlarını kullanırken bazı yaygın hatalarla karşılaşabilirsiniz. Sorun giderme durumları için bu kılavuza bakın. ## Veri tutarsızlığı \{#data-discrepancy\} **Neden**: Bu, tüm kullanıcılarınızın Adapty SDK'sına sahip uygulama sürümünü kullanmamasından kaynaklanabilir. **Çözüm**: Veri tutarlılığını sağlamak için kullanıcılarınızı Adapty SDK'sını içeren uygulama sürümüne güncellemeye zorlayabilirsiniz. ## Ağ hataları \{#network-errors\} **Neden**: Büyük olasılıkla Adapty sunucusu ile entegrasyon sunucusu arasında internet bağlantısı kesilmiştir. **Çözüm**: Bu sorunlar genellikle uzun sürmez ve yalnızca az sayıda etkinliği etkiler. ## Entegrasyon sunucusu etkinliği işleyemedi \{#integration-server-failed-to-process-the-event\} **Neden**: Entegrasyon hatalı yapılandırılmış. **Çözüm**: Dokümantasyonumuzdaki ilgili entegrasyon makalesine bakın. Adapty kontrol panelinde, üçüncü taraf araç tarafında ve uygulama kodunuzda tüm kurulum adımlarını tamamladığınızdan emin olun. ## Eksik entegrasyon verisi \{#missing-integration-data\} **Neden**: Profilde entegrasyona özgü bir ID eksik. Bu, entegrasyonun uygulama kodunda düzgün yapılandırılmamasından kaynaklanabilir. **Çözüm**: Dokümantasyonumuzdaki ilgili entegrasyon makalesine bakın. Kod parçacıklarındaki yöntemleri uygulama kodunuza eklediğinizden ve bu yöntemlerin kullanıcı profillerinizle gerçekten etkileşime girdiğinden emin olun. ## Eksik entegrasyon kimlik bilgileri \{#missing-integration-credentials\} **Neden**: Bazı entegrasyon kimlik bilgileri eksik veya hatalı. **Çözüm**: Adapty kontrol panelinde ilgili entegrasyonun tüm kimlik bilgilerini kontrol edin. Sorun, sürüm veya ortam uyumsuzluğundan kaynaklanıyor olabilir. ## Etkinliğin süresi doldu \{#the-event-has-expired\} **Neden**: Entegrasyon ayarlarında **Exclude historical events** seçeneği etkinleştirilmiş ve etkinliğin oluşturulma tarihi, sistemimizdeki profil oluşturma tarihinden önce. Bu durum, yıllar önce başlayan bir işlem zinciri, yakın zamanda oluşturulmuş bir profil için makbuz doğrulaması aracılığıyla Adapty'ye geldiğinde yaşanabilir. **Çözüm**: Yeni etkinliklerde bunun yaşanmadığından emin olun. Geçmiş etkinlikleri entegrasyona göndermek istiyorsanız **Exclude historical events** seçeneğini devre dışı bırakın. ## Devre dışı/desteklenmeyen etkinlik türü \{#disabledunsupported-event-type\} **Neden**: Etkinlik bu entegrasyon tarafından desteklenmiyor ya da entegrasyonu kurarken devre dışı bırakmış olabilirsiniz. Örneğin, `access_level_updated` etkinlikleri çoğu entegrasyon tarafından desteklenmez. **Çözüm**: Entegrasyon dokümantasyonundan bu etkinlik türünün desteklenip desteklenmediğini kontrol edin. Destekleniyorsa Adapty kontrol panelinde entegrasyon ayarlarında bu etkinlik türünün etkinleştirildiğinden emin olun. --- # File: manage-adapty-with-ai --- --- title: "Adapty'yi AI ajanları ve kodlama araçlarıyla yönetin" description: "Adapty'yi AI ile kullanmanın tüm yolları — bir kodlama ajanıyla SDK'yı entegre edin, bir LLM ile analitik verilerini çekin ve Adapty dokümanlarını AI aracınıza besleyin." --- Adapty, AI kodlama araçları ve ajanlarıyla birlikte çalışır. SDK'yı entegre etmek, analitik verileriniz hakkında soru sormak veya editörünüzden çıkmadan Adapty dokümanlarına bakmak için bunları kullanabilirsiniz. Bu sayfa mevcut seçenekleri ve her aracın kime hitap ettiğini listeler. ## Adapty SDK'yı AI ile entegre edin \{#integrate-the-adapty-sdk-with-ai\} Adapty SDK'yı bir AI kodlama aracıyla uygulamanıza eklemenin iki yolu var. Her ikisi de Cursor, Claude ve diğer AI asistanlarıyla çalışır. ### Skill tabanlı entegrasyon \{#skill-based-integration\} Adapty SDK entegrasyon skill'i, tek bir komutla tüm entegrasyonu AI kodlama aracınızdan çalıştırır. Rehberli ve otomatik bir kurulum istediğinizde kullanın. Platformunuzu seçin: [iOS](adapty-sdk-integration-skill) · [Android](adapty-sdk-integration-skill-android) · [React Native](adapty-sdk-integration-skill-react-native) · [Flutter](adapty-sdk-integration-skill-flutter) · [Unity](adapty-sdk-integration-skill-unity) · [Kotlin Multiplatform](adapty-sdk-integration-skill-kmp) · [Capacitor](adapty-sdk-integration-skill-capacitor) ### Adım adım entegrasyon \{#step-by-step-integration\} AI aracınızı entegrasyonun her aşamasında yönlendirin ve doğru dokümanları sırayla besleyin. Her adımı ilerledikçe gözden geçirmek istediğinizde kullanın. Platformunuzu seçin: [iOS](adapty-cursor) · [Android](adapty-cursor-android) · [React Native](adapty-cursor-react-native) · [Flutter](adapty-cursor-flutter) · [Unity](adapty-cursor-unity) · [Kotlin Multiplatform](adapty-cursor-kmp) · [Capacitor](adapty-cursor-capacitor) ## Adapty'yi komut satırından yönetin \{#manage-adapty-from-the-command-line\} [Adapty Developer CLI](developer-cli-quickstart), Adapty varlıklarınızı — uygulamalar, access level'lar, ürünler, paywall'lar ve placement'lar — kontrol panelini açmadan terminalden yönetmenizi sağlar. Komut satırı aracı olduğu için AI kodlama ajanınız onu doğrudan çalıştırabilir. ## Verileriniz hakkında soru sorun \{#ask-about-your-data\} Gelirleriniz, elde tutma oranlarınız, LTV ve daha fazlası gibi metriklerinizi doğal dilde sorgulamak için bir AI kodlama ajanını Export Analytics API'sine yönlendirin. MCP sunucusuna gerek yok. [Analitik verileriniz hakkında AI'a sorun](export-analytics-with-ai) ## AI aracınıza Adapty dokümanlarını verin \{#give-your-ai-tool-the-adapty-docs\} ### Düz metin dokümanlar \{#plain-text-docs\} Her Adapty dokümanı Markdown olarak mevcuttur — sayfa URL'sine `.md` ekleyin veya başlığın altındaki **Copy for LLM** seçeneğine tıklayın. Daha geniş bağlam için aracınıza [`llms.txt`](https://adapty.io/docs/tr/llms.txt) dizinini veya [`ios-llms.txt`](https://adapty.io/docs/tr/ios-llms.txt) gibi platforma özgü bir alt kümeyi verin. ### Context7 \{#context7\} [Context7](https://context7.com/adaptyteam/adapty-docs), Adapty dokümanlarını AI aracınıza sunan bir MCP sunucusudur; ancak yalnızca kod parçacıklarını dizinler — tam metni değil. Hızlı kod örnekleri için kullanın; kapsamlı rehberlik için yukarıdaki düz metin dokümanları aracınıza verin. Context7, Cursor, Claude Code, Windsurf ve diğer MCP uyumlu araçlarla çalışır. --- # File: export-analytics-with-ai --- --- title: "Analitik verileriniz hakkında YZ'ye sorun" description: "Export Analytics API'yi kullanarak düz dille bir YZ kodlama ajanı aracılığıyla Adapty analizlerinizi sorgulayın." --- Adapty analitiğiniz hakkında düz dille bir yapay zeka kodlama ajanına soru sorun — gelir, dönüşümler, elde tutma, LTV — ve sayıları sizin için çeksin. [Export Analytics API](https://adapty.io/docs/tr/export-analytics-api.md)'ye API çağrısı yapabilen bir araç yönlendirin; metriklerinizi isteğe bağlı olarak sorgulasın. ## Ne hakkında soru sorabilirsiniz \{#what-you-can-ask-about\} Export Analytics API, Adapty kontrol paneli grafiklerinde gördüğünüz metriklerin aynısını döndürür. Her metriğin kendine ait bir işlemi vardır: | Metrik | Kapsadığı alan | İşlem | | --- | --- | --- | | Gelir, MRR, ARR, ARPU | Dönem, ülke veya kampanyaya göre gruplandırılmış, zaman içinde kazanılan para | [retrieveAnalyticsData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveAnalyticsData.md) | | Kohort tutma | Belirli bir kohorttan abonelerin ne kadar süre ödeme yaptığı | [retrieveCohortData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveCohortData.md) | | Dönüşüm oranları | Kaç kullanıcının bir adımdan veya kanaldan bir sonrakine geçtiği | [retrieveConversionData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveConversionData.md) | | Kayıp ve huni | Kullanıcıların nerede ayrıldığı ve abonelikten ne kadar hızlı çıktığı | [retrieveFunnelData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveFunnelData.md) | | Yaşam boyu değer (LTV) | Zaman içinde kullanıcı segmenti başına ortalama gelir | [retrieveLTVData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveLTVData.md) | | Elde tutma | Belirli sayıda gün sonra hâlâ aktif olan kullanıcıların oranı | [retrieveRetentionData](https://adapty.io/docs/tr/api-export-analytics/operations/retrieveRetentionData.md) | API referansının tam parametre ve filtre listesi için [API referansına](https://adapty.io/docs/tr/api-export-analytics.md) bakın. ## Başlamadan önce \{#before-you-start\} Üç şeye ihtiyacınız var: - **Veri içeren bir Adapty hesabı**: API, kontrol panelinizin grafiklerindeki metriklerin aynısını döndürür; bu nedenle uygulamanızın zaten analitik verileri toplaması gerekir. - **Gizli bir API anahtarı**: [App settings → General](https://app.adapty.io/settings/general) sayfasındaki **Secret key** alanında bulabilirsiniz. Anahtarlar uygulamaya özgüdür; her uygulama için ayrı bir anahtar kullanın. Ajanınızın sohbete yapıştırmanıza gerek kalmadan okuyabilmesi için anahtarı bir ortam değişkeninde saklayın (örneğin `ADAPTY_SECRET_KEY`). - **API çağrısı yapabilen bir yapay zeka aracı**: Örneğin Claude Code, Cursor veya fetch aracına sahip Claude Desktop. claude.ai veya ChatGPT gibi sıradan sohbet araçları API'yi doğrudan çağıramaz. ## Aracınıza API Spesifikasyonunu Tanıtın \{#give-your-agent-the-api-spec\} [OpenAPI spesifikasyonu](https://adapty.io/docs/tr/api-specs/export-analytics-api.yaml), her endpoint'i, kimlik doğrulama başlığını, istek gövdesini ve örnek yanıtları açıklar. Aracınız bu spesifikasyona sahip olduğunda, siz hiç kod yazmadan doğru istekleri oluşturabilir. Spesifikasyonu URL ile aracınıza tanıtın: - **URL'yi yapıştırın**: Aracınız URL'leri getirebiliyorsa, `https://adapty.io/docs/tr/api-specs/export-analytics-api.yaml` adresini verin ve spec'i okumasını isteyin. - **Bir fetch aracı kullanın**: Aracınızda URL'leri getiren bir araç varsa (örneğin, bir MCP fetch sunucusu), aynı URL'yi gösterin. Spec, temel URL'yi `https://api-admin.adapty.io` olarak ayarlar; dolayısıyla anahtarınız ortamda olduğunda aracınızın ihtiyacı olan her şey hazır olur. ## Verileriniz Hakkında Soru Sorun \{#ask-about-your-data\} Spec yüklenmiş ve anahtarınız bir ortam değişkeninde tanımlıyken, istediğiniz metriği düz dille anlatın. Örnek komutlar: ``` What was my MRR at the end of each month this year, and how does it compare to last year? Show my trial-to-paid conversion rate for the last 90 days, broken down by product. Which countries drive the most revenue from my yearly subscription? Top 10. How is week-1 retention trending for subscribers who started in the last 6 months? What's the refund rate on my annual plan since launch, by month? Compare LTV for paid-campaign users vs. organic over the last year, and export it as CSV. ``` Agent, isteğinizi doğru işleme eşler, anahtarı ortam değişkeninden okur ve veriyi döndürür. Yanıtlar varsayılan olarak JSON formatındadır. Elektronik tabloya hazır bir dosya istediğinizde CSV isteyin — agent, istek gövdesinde `format` değerini `csv` olarak ayarlar. :::warning Gizli anahtarınızı ortam değişkeninde saklayın — sohbete yapıştırmayın ya da bir kurallar dosyasına kaydetmeyin. Anahtarlar uygulamaya özel olduğundan, sızma durumunda **Settings → General** bölümünden anahtarınızı yenileyin. Bkz. [API anahtarlarını yenileme](https://adapty.io/docs/tr/export-analytics-api-authorization.md). ::: ## Tekrarlayan kullanım için bir kez ayarlayın \{#set-up-once-for-repeated-use\} Her oturumda tekrar ayarlama yapmamak için spec ve key'i ajanınızın yeniden kullanabileceği bir yere kaydedin: - **Spec linkini kaydedin**: Spec URL'sini ajanınızın kurallar veya bellek dosyasına ekleyin (örneğin bir `CLAUDE.md` ya da Cursor kurallar dosyası), böylece her oturumda otomatik yüklenir. - **Anahtarı ortam değişkenlerinizde saklayın**: `ADAPTY_SECRET_KEY`'i shell profilinizde veya aracın gizli deposunda tutun, böylece bir daha yapıştırmanıza gerek kalmaz. - **Yeniden kullanılabilir prompt'ları kaydedin veya özel bir beceri oluşturun**: Sık kullandığınız soruları kayıtlı prompt olarak tutun ya da bunları özel bir beceri veya slash komutuyla sarmalayın; böylece ajanınız raporları isteğe bağlı çalıştırır. ## Sınırlamalar \{#limits\} Bu kısıtlamaları aklınızda bulundurun: - **Hız sınırı**: API, API anahtarı başına saniyede 2 istek yapılmasına izin verir. Bu sınırı aşmanız durumunda `429 Too Many Requests` hatası döner. Aracınıza `429` alındığında bekleyip tekrar denemesini söyleyin. - **Uygulamaya özel anahtarlar**: Her anahtar yalnızca bir uygulama için çalışır. Birden fazla uygulamadan veri çekmek için her biri için ilgili anahtarı sağlayın. - **Çıktı formatı**: Yanıtlar varsayılan olarak JSON formatındadır. CSV dışa aktarımı için istek gövdesinde `format` değerini `csv` olarak ayarlayın. Kimlik doğrulama ve istek kurallarının tamamı için [Yetkilendirme ve istek formatı](https://adapty.io/docs/tr/export-analytics-api-authorization.md) sayfasına bakın. --- # File: handle-webhooks-with-ai --- --- title: "Adapty abonelik etkinliklerini webhook'larla yönetin" description: "Adapty abonelik etkinliklerini sunucunuzda webhook'larla alın ve yönetin — uç nokta kurulumu, kimlik doğrulama, yük ve test tek sayfada." --- Webhook'lar, sunucunuzun Adapty abonelik olaylarını gerçek zamanlı olarak almasını sağlar — satın almalar, yenilemeler, iptaller, ödeme sorunları ve iadeler — böylece erişim izni verebilir, backend'inizi senkronize edebilir veya iş akışlarını tetikleyebilirsiniz. Bu kılavuz, uç noktadan doğrulanmış ve test edilmiş bir entegrasyona kadar tüm süreci tek sayfada anlatır ve bir AI kodlama ajanının sizin teknoloji yığınınız için handler'ı nasıl yazacağını gösterir. :::tip Bir AI kodlama ajanı mı kullanıyorsunuz? Başlığın altındaki **Copy for LLM** butonuna tıklayın ve bu sayfanın tamamını ajanınıza yapıştırın — kurulum, payload ve handler mantığı için ihtiyaç duyduğu her şey orada. ::: ## Adapty webhook'ları nasıl çalışır \{#how-adapty-webhooks-work\} - **Tek yönlü ve gerçek zamanlı**: Adapty, bir olay gerçekleştiğinde sunucunuza HTTP `POST` isteği gönderir — herhangi bir polling gerekmez. - **İki tür istek**: Entegrasyonu kaydettiğinizde gönderilen tek seferlik bir doğrulama isteği ve süregelen abonelik olayları. - **Ortam başına bir URL**: Production ve sandbox için ayrı bir endpoint yapılandırırsınız. - **Her isteği onaylamanız gerekir**: Hızlıca `2xx` durum koduyla yanıt verin; başarısız olması durumunda Adapty isteği yeniden dener. ## Uç noktanızı oluşturun \{#build-your-endpoint\} İki istek türünü işleyen, herkese açık bir HTTPS uç noktası oluşturun: - **Doğrulama isteği**: Entegrasyonu kaydettiğinizde bir kez gönderilir. JSON gövdesi boştur (`{}`). `2xx` durum kodu ve bir JSON gövdesiyle yanıt verin. - **Abonelik olayları**: Olayı gövdede taşıyan süregelen `POST` istekleri. 10 saniye içinde `200` ile yanıt verin, ağır işlemleri ise asenkron olarak gerçekleştirin. Gizli bir dize seçin ve bunu bir ortam değişkeni olarak saklayın (örneğin, `ADAPTY_WEBHOOK_SECRET`). Her istekte, `Authorization` başlığının bu değerle eşleştiğini doğrulayın; eşleşmiyorsa isteği reddedin — aynı gizli diziyi bir sonraki adımda kontrol paneline gireceksiniz. ```javascript title="webhook.js" const app = express(); app.use(express.json()); const WEBHOOK_SECRET = process.env.ADAPTY_WEBHOOK_SECRET; app.post("/adapty/webhook", (req, res) => { // 1. Verify the shared secret Adapty echoes back. if (req.get("Authorization") !== WEBHOOK_SECRET) { return res.sendStatus(401); } // 2. Acknowledge fast, then process asynchronously. res.status(200).json({}); // 3. The verification request has an empty body — nothing to handle. const event = req.body; if (!event.event_type) return; switch (event.event_type) { case "subscription_started": case "subscription_renewed": case "trial_converted": // Grant or extend access. break; case "subscription_expired": case "subscription_refunded": // Revoke access. break; default: break; } }); app.listen(3000); ``` Entegrasyonu yapılandırmadan önce endpoint'i herkese açık bir HTTPS URL'sine deploy edin — Adapty, kaydettiğiniz anda doğrulama isteğini gönderir. ### Temel olaylar ve payload \{#key-events-and-the-payload\} Her olay aynı zarfı paylaşır. Alanlar olay türüne, mağazaya ve etkinleştirdiğiniz seçeneklere göre değişir. İşte kısaltılmış bir `subscription_started` olayı: ```json title="Example event" { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "event_type": "subscription_started", "event_datetime": "2024-11-15T10:45:36.181000+0000", "event_properties": { "store": "play_store", "currency": "USD", "price_usd": 4.99, "vendor_product_id": "onemonth_no_trial", "transaction_id": "0000000000000000", "original_transaction_id": "0000000000000000", "subscription_expires_at": "2024-12-15T10:45:36.181000+0000", "profile_event_id": "00000000-0000-0000-0000-000000000000" }, "event_api_version": 1 } ``` En sık karşılaşacağınız olaylar: | Etkinlik türü | Ne zaman tetiklenir | | --- | --- | | `subscription_started` | Bir kullanıcı ücretli abonelik başlattığında | | `subscription_renewed` | Bir abonelik yenilenip başarıyla faturalandığında | | `subscription_renewal_cancelled` | Bir kullanıcı otomatik yenilemeyi kapattığında (erişim sona erme tarihine kadar devam eder) | | `subscription_expired` | Yenilenmeyen bir abonelik sona erip erişim bittiğinde | | `trial_started` | Bir kullanıcı ücretsiz deneme başlattığında | | `trial_converted` | Deneme süresi ücretli aboneliğe dönüştüğünde | | `billing_issue_detected` | Yenileme ödemesi başarısız olduğunda | | `subscription_refunded` | Bir abonelik satın alımı iade edildiğinde | Tam etkinlik listesi ve her alan için bkz. [Webhook etkinlik türleri ve alanları](https://adapty.io/docs/tr/webhook-event-types-and-fields.md). :::warning Etkinlikleri `event_datetime` alanına göre sıralamayın — bu, etkinliğin iş zamanıdır; etkinlikler sıra dışı gelebilir ya da aynı zaman damgasını paylaşabilir. Kendi alım zamanınıza göre sıralayın ve `profile_event_id` ya da işlem kimliklerini kullanarak tekrar kayıtları temizleyin. ::: ## Adapty'de webhook'u yapılandırma \{#configure-the-webhook-in-adapty\} 1. Adapty Kontrol Paneli'nde [Integrations → Webhook](https://app.adapty.io/integrations/customwebhook) bölümünü açın. 2. Entegrasyonu etkinleştirin. 3. **Production endpoint URL** alanına dağıttığınız endpoint'in HTTPS URL'sini girin. 4. **Authorization header value for production endpoint** alanına, endpoint'inizin doğruladığı gizli anahtarı girin. Adapty bu değeri her istekte `Authorization` başlığıyla geri gönderir. Zorunlu değildir ancak kesinlikle önerilir. 5. Önce sandbox ortamında test etmek istiyorsanız **Sandbox endpoint URL** ve ilgili **Authorization header value** alanlarını da doldurun. 6. **Save** düğmesine tıklayın. Adapty hemen endpoint'inize doğrulama isteği gönderir; endpoint'iniz kurulumu tamamlamak için `2xx` yanıtı döner. Hangi etkinliklerin gönderileceğini seçmek, etkinlik adlarını eşleştirmek veya isteğe bağlı alanları (deneme fiyatı, geçmiş etkinlikler, attribution, kullanıcı nitelikleri, Play Store token) etkinleştirmek için bkz. [Webhook entegrasyonunu ayarlama](https://adapty.io/docs/tr/set-up-webhook-integration.md). ## AI kodlama aracınızla oluşturun \{#build-it-with-your-ai-coding-agent\} AI kodlama aracınıza bu kılavuzu ve referans dokümanları Markdown olarak verin (herhangi bir sayfa URL'sine `.md` ekleyin), kullandığınız teknolojiyi belirtin ve handler'ı oluşturmasını sağlayın: - [Webhook olay türleri ve alanları](https://adapty.io/docs/tr/webhook-event-types-and-fields.md) - [Webhook entegrasyonunu kurma](https://adapty.io/docs/tr/set-up-webhook-integration.md) Örnek prompt: ``` Read these Adapty webhook docs, then write a webhook handler for my Express app: verify the Authorization header against ADAPTY_WEBHOOK_SECRET, answer the verification request, acknowledge events with 200, and grant or revoke access based on event_type. ``` The agent writes the handler code, but it can't deploy your endpoint or configure the dashboard — host the endpoint yourself and set the URL and secret in **Integrations → Webhook**. ## Webhook'unuzu test edin \{#test-your-webhook\} Üretime geçmeden önce sandbox ortamında test edin: 1. Yukarıda açıklandığı gibi sandbox endpoint'ini ve secret'ı ayarlayın. 2. Sandbox uygulamanızda bir satın alma yapın, deneme başlatın veya olay tetiklemek için iade isteyin. 3. Entegrasyonun **Last sent events** bölümünü açın. Başarıyla iletilen bir olay **Success** durumunu gösterir. Bir olay **Sending failed** gösteriyorsa, sunucunuz 200–399 aralığı dışında bir durum kodu döndürmüş demektir — ayrıntılar için durumun üzerine gelin. Tam test adımları için bkz. [Webhook entegrasyonunu test etme](https://adapty.io/docs/tr/test-webhook.md). ## Sınırlamalar \{#limits\} - **10 saniye içinde yanıt verin**: Adapty zamanında yanıt alamazsa denemeyi başarısız sayar ve yeniden dener. - **Yeniden denemeler**: Durum kodunuz 200–404 aralığının dışındaysa Adapty üstel geri çekilme ile yeniden dener — 24 saat içinde en fazla 9 deneme. - **İptal gecikmesi**: İptal olaylarının ulaşması 2 saate kadar sürebilir. - **Ortam başına tek URL**: Olayları birden fazla servise iletmek için webhook'u kendi backend'inize yönlendirin ve oradan dağıtın. --- # File: server-side-api-with-ai --- --- title: "Backend'inizden abonelik erişimini kontrol edin ve izin verin" description: "Bir kullanıcının aktif bir aboneliğe sahip olup olmadığını kontrol etmek ve erişimi manuel olarak vermek için Adapty sunucu tarafı API'sini kullanın; bir AI kodlama ajanının yardımıyla." --- Arka ucunuzdan, bir kullanıcının aktif aboneliğinin olup olmadığını kontrol etmek ve erişimi manuel olarak vermek için Adapty sunucu tarafı API'sini kullanın. Bu kılavuz en yaygın iki çağrıyı — `getProfile` ve `grantAccessLevel` — ele alır ve bir AI kodlama ajanının sizin için entegrasyonu nasıl yazabileceğini gösterir. :::tip Bir AI kodlama ajanı mı kullanıyorsunuz? Başlığın altındaki **Copy for LLM** seçeneğine tıklayın ve bu sayfanın tamamını ajanınıza yapıştırın — ihtiyaç duyduğu çağrılar, alanlar ve dikkat edilmesi gereken noktalar orada mevcut. ::: ## Başlamadan önce \{#before-you-start\} - **Gizli API anahtarı**: [App settings → General](https://app.adapty.io/settings/general) sayfasında, **Secret key** alanında bulabilirsiniz. Anahtarlar uygulamaya özeldir. Bir ortam değişkeninde saklayın (örneğin `ADAPTY_SECRET_KEY`) ve `Authorization: Api-Key {key}` olarak gönderin. - **Temel URL**: Tüm istekler `https://api.adapty.io` adresine gider. - **Kullanıcıyı tanımlamanın bir yolu**: `adapty-customer-user-id` (kendi kullanıcı kimliğiniz — yalnızca uygulamada kullanıcıları tanımlıyorsanız çalışır) veya `adapty-profile-id` (Adapty profil kimliği) gönderin. İkisi birbirinin yerine kullanılabilir; birini seçin. ## Abonelik durumunu kontrol etme \{#check-a-subscription\} Durumu kontrol etmek için `GET` yöntemiyle `getProfile` çağrısı yapın ve kullanıcı tanımlayıcısını header olarak geçirin — istek gövdesi gerekmez. ```javascript title="check-access.js" const res = await fetch("https://api.adapty.io/api/v2/server-side-api/profile/", { headers: { "Authorization": `Api-Key ${process.env.ADAPTY_SECRET_KEY}`, "adapty-customer-user-id": userId, }, }); const { data } = await res.json(); function hasActiveAccess(profile, accessLevelId = "premium") { const level = profile.access_levels?.find(a => a.access_level_id === accessLevelId); if (!level) return false; if (level.is_in_grace_period) return true; if (!level.expires_at) return true; // lifetime / non-expiring return new Date(level.expires_at) > new Date(); // not expired yet } if (hasActiveAccess(data)) { // unlock premium features } ``` SDK profilinin aksine, sunucu tarafı yanıtında **`is_active` alanı bulunmaz**. Durumu `access_levels[].expires_at` alanından kendiniz türetmeniz gerekir: `null` değeri süresiz erişim anlamına gelir, gelecekteki bir tarih aktif olduğunu, geçmişteki bir tarih ise sona erdiğini gösterir. `is_in_grace_period` durumunu hâlâ aktif olarak değerlendirin. Profil ve access level alanlarının tamamı için [getProfile](https://adapty.io/docs/tr/api-adapty/operations/getProfile.md) sayfasına bakın. ## Erişimi manuel olarak ver \{#grant-access-manually\} Satın alma olmaksızın ücretli özelliklerin kilidini açmak için — promosyon kodları, yatırımcı veya beta erişimi, destek talepleri — `grantAccessLevel` metodunu `POST` ile çağırın. ```javascript title="grant-access.js" await fetch("https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/", { method: "POST", headers: { "Authorization": `Api-Key ${process.env.ADAPTY_SECRET_KEY}`, "adapty-customer-user-id": userId, "Content-Type": "application/json", }, body: JSON.stringify({ access_level_id: "premium" }), // geçici erişim için "expires_at" ekleyin }); ``` - **Access level'ın kontrol panelinizde zaten mevcut olması gerekir** (**Access levels**) — `access_level_id` yeni bir isim değil, mevcut access level'ın tanımlayıcısıdır. - **Manuel olarak verilen erişimler analitikte görünmez.** Yalnızca webhook entegrasyonunuza ve Event Feed'e iletilir; bu nedenle gelir ve dönüşüm grafikleri bunları yansıtmaz. İstek ve yanıt ayrıntıları için [grantAccessLevel](https://adapty.io/docs/tr/api-adapty/operations/grantAccessLevel.md) sayfasına bakın. ## AI kodlama ajanınızla geliştirin \{#build-it-with-your-ai-coding-agent\} AI kodlama ajanınıza bu kılavuzu ve API spesifikasyonunu Markdown olarak verin (herhangi bir sayfa URL'sine `.md` ekleyin), kullandığınız stack'i belirtin ve çağrıları yazdırmasına izin verin: - [OpenAPI spec](https://adapty.io/docs/tr/api-specs/adapty-api.yaml) - [getProfile](https://adapty.io/docs/tr/api-adapty/operations/getProfile.md) - [grantAccessLevel](https://adapty.io/docs/tr/api-adapty/operations/grantAccessLevel.md) Örnek prompt: ``` Using the Adapty server-side API spec, write backend functions to check whether a user has an active "premium" access level (GET /profile/, derive status from expires_at — there's no is_active field) and to grant it (grantAccessLevel). Authenticate with ADAPTY_SECRET_KEY and identify users by adapty-customer-user-id. ``` The agent writes the code, but it can't run your backend or set your keys — you provide the secret key and the user identifiers. ## Sınırlar \{#limits\} - **Hız sınırı**: Uygulama başına dakikada en fazla 40.000 istek. - **Uygulamaya özel anahtarlar**: Her anahtar yalnızca bir uygulama için geçerlidir; her uygulama için doğru anahtarı kullanın. - **Bir tanımlayıcı zorunludur**: Her istek `adapty-customer-user-id` veya `adapty-profile-id` içermelidir. --- # File: test-purchases-in-sandbox --- --- title: "Sandbox testi" description: "İşlemlerin sorunsuz gerçekleştiğinden emin olmak için sandbox ortamında satın almaları test edin." --- Adapty Kontrol Paneli'nde ve mobil uygulamanızda her şeyi yapılandırdıktan sonra uygulama içi satın alma testlerini yapmaya hazırsınız. **Not:** Test araçlarının hiçbiri, kullanıcılardan ürün satın alma testi sırasında ücret almaz. App Store, test ortamlarında gerçekleştirilen satın alma veya iade işlemleri için e-posta göndermez. :::note **Sandbox işlemleri tüm analitik grafiklerden hariç tutulur.** Yine de bireysel profil sayfalarında ve etkinlik akışında görünürler. ::: :::info Uygulama içi satın alma testine devam etmek için şunlardan emin olun: - Mağaza entegrasyonu, ürün ekleme ve Adapty SDK entegrasyonuna ilişkin [hızlı başlangıç](quickstart) kılavuzlarını tamamladınız. - Ürününüz App Store Connect'te [**Ready to submit**](InvalidProductIdentifiers#step-2-check-products) olarak işaretlenmiş. ::: ## Sandbox testi \{#sandbox-testing\} <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/hq4PRU-vuik?si=m5F5Sj6iLEJ-2q6n" title="YouTube video oynatıcı" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> :::info Uygulama içi satın almaları gerçek bir cihazda test etmenizi öneririz. Sandbox satın almalar simülatörlerde çalışabilse de, ödeme diyalogları ve biyometrik doğrulama dahil tüm flow'ları tam olarak test etmek için gerçek bir cihaz gereklidir. ::: Uygulama içi satın almaları test etmenin iki ana yolu vardır: - **Xcode'da derleyip test cihazında çalıştırmak**: Geliştiriciler ve QA mühendisleri için idealdir. - **TestFlight ile sandbox test hesabı kullanmak**: Diğer herkes için uygundur. Her iki seçenek de aşağıdaki kılavuzda ele alınmaktadır. ### Adım 1. App Store Connect'te Sandbox test hesabı oluşturma \{#step-1-create-sandbox-test-account-in-app-store-connect\} :::warning Satın alma geçmişinizin temiz olduğundan emin olmak için yeni bir Sandbox test hesabı oluşturun. Mevcut bir hesabı yeniden kullanırsanız, daha önce satın alınan ürünler kullanılabilir olmaya devam eder ve bunları tekrar satın almayı test edemezsiniz. ::: Birkaç tıklamayla yeni bir Sandbox test hesabı oluşturabilirsiniz: 1. App Store Connect'te [**Users and Access** > **Sandbox** > **Test Accounts**](https://appstoreconnect.apple.com/access/users/sandbox) bölümüne gidin ve **+** düğmesine tıklayın. <img src="/assets/shared/img/add-sandbox-user.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Test kullanıcısının bilgilerini girin. Test etmeyi planladığınız **Country or Region** seçeneğini mutlaka belirtin; bu seçenek, ilgili bölgedeki ürün erişilebilirliğini ve satın alma para birimini etkiler. :::tip - Gmail veya iCloud kullanıyorsanız, mevcut e-posta adresinizi [artı işareti alt adresleme](https://www.wikihow.com/Use-Plus-Addressing-in-Gmail) yöntemiyle yeniden kullanabilirsiniz. - Var olmayan rastgele bir e-posta adresi de kullanabilirsiniz; ancak test cihazında oturum açarken iki faktörlü kimlik doğrulamayı (2FA) reddettiğinizden emin olun. ::: <img src="/assets/shared/img/57c3a7c-apple_new_test_account.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create**'e tıklayın. ### Adım 2. Geliştirici modunu etkinleştir \{#step-2-enable-the-developer-mode\} :::note Test cihazınızda Geliştirici modu **zaten etkinse** veya **Mac cihazınız yoksa** bu adımı atlayın. ::: Xcode yüklü bir Mac ve test cihazı kablosuna ihtiyacınız olacak: 1. Mac'inizde Xcode'u açın. TestFlight ile uygulama içi satın almaları test edecekseniz yalnızca Xcode'un yüklü olması yeterlidir; uygulamanın orada açık olmasına gerek yoktur. 2. Test cihazınızı kablo ile Mac'e bağlayın. 3. Test cihazınızda **Settings > Privacy & Security > Developer Mode** yoluna gidin ve **Developer Mode**'u açın. ### Adım 3. Uygulamayı TestFlight'tan indirin \{#step-3-download-the-app-from-testflight\} :::info Bu adım yalnızca TestFlight ile test yapıyorsanız geçerlidir. Uygulamayı Xcode'da derliyorsanız bu adımı atlayın. ::: Uygulamanızı TestFlight'a gönderme hakkında ayrıntılı bilgi için [Apple belgelerine](https://developer.apple.com/documentation/StoreKit/testing-in-app-purchases-with-sandbox#Prepare-for-sandbox-testing) bakın. TestFlight uygulamasını indirmeden önce test cihazınızda üretim Apple Hesabınızla oturum açtığınızdan emin olun. Ardından test etmek istediğiniz uygulamayı TestFlight'tan indirin. :::danger Uygulamayı indirdikten sonra açmayın. Doğrudan sonraki adımlara geçin. Yanlışlıkla açtıysanız, test cihazınızdan kaldırıp tekrar indirin. Aksi takdirde satın alma geçmişiniz temiz olmayabilir ve uygulama içi satın alma testleri hatalara yol açabilir. ::: ### Adım 4. Sandbox test hesabına geçin \{#step-4-switch-to-sandbox-test-account\} <Details> <summary>Mac kullanmıyor musunuz? İşte size özel bir ipucu</summary> macOS üzerinde çalışmıyorsanız, Xcode aracılığıyla sandbox hesabına geçemezsiniz. Ancak bunu test cihazınızda doğrudan yapabilirsiniz: 1. Test cihazınızda **Settings > Your Apple Account > Media & Purchases** bölümüne gidin. 2. Açılan menüden **Sign Out** seçeneğini seçin. 3. TestFlight'tan indirilen uygulamayı açın ve bir ürün satın almayı deneyin. 4. Oturum açmanız istendiğinde, sandbox ortamına geçmek için sandbox hesabı bilgilerinizi girin. </Details> Sandbox hesabınıza geçmek için: 1. Test cihazınızda **Settings > Your Apple Account > Media & Purchases** bölümüne gidin. 2. Açılan menüden **Sign Out** seçeneğini seçin. 3. **Settings > Developer** bölümüne gidin. Eğer **Developer** seçeneği görünmüyorsa, [2. adımda etkinleştirdiğinizden](#step-2-enable-the-developer-mode) emin olun. <img src="/assets/shared/img/devmode.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Sandbox Apple Account** bölümüne gidin ve **Sign In** düğmesine dokunun. <img src="/assets/shared/img/sandbox-acc.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Sandbox Apple Account bilgilerinizle giriş yapın. ### Adım 5. Satın alma geçmişini temizle \{#step-5-clear-purchase-history\} Yeni bir Sandbox test hesabı oluşturup bu hesaba geçiş yaptıysanız, bu adımı atlayabilirsiniz; çünkü bu adım yalnızca aynı Sandbox test hesabıyla tekrarlanan testler için geçerlidir. 1. Test cihazınızda **Settings > Developer > Sandbox Apple Account** bölümüne gidin. 2. Açılan menüden **Manage** seçeneğini belirleyin. 3. **Account Settings** bölümüne gidip **Clear Purchase History** öğesine dokunun. :::danger Bu adım, aynı Sandbox test hesabını kullanarak her test tekrarladığınızda gereklidir. Bu durumda, satın alma geçmişi önbelleğini test cihazında temizlemek için [Sandbox test hesabınızdan çıkış yapmanız](#step-4-switch-to-sandbox-test-account) ve ardından tekrar giriş yapmanız gerekecektir. ::: ### Adım 6. Xcode'da derleyin ve çalıştırın \{#step-6-build-in-xcode-and-run\} :::info Bu adım yalnızca Xcode derlemesiyle test ediyorsanız geçerlidir. TestFlight kullanıyorsanız bu adımı atlayın. ::: 1. Test cihazınızı Mac'inize bağlayın. 2. Xcode'u açın. 3. Uygulamayı bağlı cihazda derleyip çalıştırmak için araç çubuğundaki **Run** düğmesine tıklayın ya da **Product > Run** yolunu izleyin. Derleme başarılı olursa Xcode, uygulamayı cihazınızda başlatır ve hata ayıklama alanında bir hata ayıklama oturumu açar. Uygulamanız artık cihazda test edilmeye hazır. ### Adım 7. Test satın alması yapın \{#step-7-make-test-purchase\} Uygulamayı açın ve bir paywall üzerinden test satın alması gerçekleştirin. İşlem tamamlandıktan sonra, sonuçlarınızı kontrol etmek için [test satın almalarını doğrulama](validate-test-purchases) makalesine gidin. ### Adım 8. Test etmeye devam edin \{#step-8-keep-testing\} Artık test ortamınız tamamen hazır. Tekrar test etmek istiyorsanız, [sandbox hesabının satın alma geçmişini temizleyin](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings/). ## Test sorunları \{#testing-issues\} Aşağıda bir uygulamayı test ederken karşılaşabileceğiniz yaygın sorunlar listelenmiştir. ### TestFlight sorunları \{#testflight-issues\} **Sandbox test hesabı kullanmadan TestFlight kullanırsanız** satın alma geçmişinizi temizleyemezsiniz; bu durum çeşitli sorunlara ve hatalı test sonuçlarına yol açar. Yanlışlıkla [Sandbox test hesabına geçmeyi](#step-4-switch-to-sandbox-test-account) unutup uygulamayı bir kez bile açtıysanız, TestFlight satın alma geçmişinizi üretim Apple hesabınıza bağlar ve beklenmedik sorunlara neden olur. Düzeltmek için şu adımları izleyin: 1. Uygulamayı test cihazından kaldırın. 2. [Sandbox testi](#sandbox-testing) adımlarını takip edin. :::note Yalnızca uygulamayı yeniden yüklemek yeterli değildir; aynı zamanda Sandbox test hesabına geçmeniz, satın alma geçmişini temizlemeniz ve uygulamayı Sandbox test hesabıyla başlatmanız gerekir. ::: ### Paylaşılan access level sorunları \{#shared-access-levels-issues\} Aynı Sandbox test hesabıyla tekrar test yaparsanız, test kullanıcısı için [paylaşılan access level'larla](sharing-paid-access-between-user-accounts) beklenmedik davranışlarla karşılaşabilirsiniz. Kullanıcının devralınan bir access level'a sahip olup olmadığını kontrol etmek için Adapty Kontrol Paneli'nden [Profiles & Segments](https://app.adapty.io/profiles/users) sayfasına gidin ve kullanıcının profilini açın. <thinking> The user wants me to translate a fragment of MDX documentation from English to Turkish. Let me analyze what needs to be translated and what needs to be preserved. 1. The `` component with the `<img>` tag - preserve the JSX exactly, only translate attribute values that are human-readable phrases (but here there are no human-readable attribute values to translate) 2. The prose text after the component needs to be translated. Let me translate the prose: "If the user has an inherited access level, follow these steps for accurate testing results:" Turkish translation: "Kullanıcının miras alınan bir access level'ı varsa, doğru test sonuçları için şu adımları izleyin:" Note: "access level" stays as "access level" per glossary. </thinking> <Zoom> <img src="/assets/shared/img/profile-access-level-origin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Kullanıcının miras alınan bir access level'ı varsa, doğru test sonuçları elde etmek için şu adımları izleyin: 1. Üst profili silin. 2. Uygulamayı test cihazından kaldırın. 3. [Uygulamayı TestFlight'tan indirin](#step-3-download-the-app-from-testflight). 4. [Sandbox test hesabına geçin](#step-4-switch-to-sandbox-test-account). 5. [Satın alma geçmişini temizleyin](#step-5-clear-purchase-history). 6. [Uygulamayı açın ve test satın alımınızı yapın](#step-6-make-test-purchase). :::note Satın alma geçmişini temizlemek, mağaza tarafındaki satın almayı sıfırlar. Üst profili silmek yalnızca Adapty tarafındaki kaydı kaldırır. Yeniden kullanılan bir hesabın neden erişimi koruduğunu ve hangi sıfırlama işlemlerinin gerçekten işe yaradığını öğrenmek için bkz. [Bir test kullanıcısının aboneliğini sıfırlama](#resetting-a-testers-subscription). ::: ### TestFlight'ta uygulamayı güncelleme \{#updating-app-in-testflight\} TestFlight uygulaması güncellendiyse: 1. Uygulamayı test cihazından kaldırın. 2. [Uygulamayı TestFlight'tan indirin](#step-3-download-the-app-from-testflight). 3. [Sandbox test hesabına geçin](#step-4-switch-to-sandbox-test-account). 4. [Satın alma geçmişini temizleyin](#step-5-clear-purchase-history). 5. [Uygulamayı açın ve test satın alımınızı gerçekleştirin](#step-6-make-test-purchase). ## Test kullanıcısının aboneliğini sıfırlama \{#resetting-a-testers-subscription\} Sandbox ortamında bir satın alma, Adapty profiline değil **Apple sandbox hesabına** aittir. Profilde yaptığınız işlemler (profili silmek veya access level düzenlemek), satın almayı mağaza hesabından kaldırmaz. Sonraki yeniden yükleme veya senkronizasyonda SDK aynı işlemi yeniden profille ilişkilendirir ve test kullanıcısı erişimini geri kazanır. Aşağıdaki tablo, her sıfırlama işleminin neleri değiştirdiğini ve test kullanıcısının ardından ne gördüğünü göstermektedir. | Eylem | Adapty profili | Apple sandbox hesabı | Test sonrası erişim | | :-------------------------------------------------------------------------------- | :------------------------------------------------------ | :--------------------- | :------------------------------------------------------------------------------------------------- | | Adapty Kontrol Paneli'nde profili sil | Silindi | Değişmedi | **Geri döner** — yeniden yüklemede, yeni bir profil aynı işlem zincirine yeniden bağlanır | | [Profil silme API'si](api-adapty/operations/deleteProfile) aracılığıyla profili sil | Silindi | Değişmedi | **Geri döner** — Kontrol Paneli'nden silmekle aynı sonuç | | **Add access level** ile geçmiş bir sona erme tarihi ekle | Sonraki senkronizasyonda geçersiz kılınır | Değişmedi | Sonraki yenilemede **geri döner** — canlı abonelik ileriki bir sona erme tarihi uygular | | [Erişim seviyesini iptal etme API'si](api-adapty/operations/revokeAccessLevel) çağrısı yap | Şu an sona erer, `access_level_updated` (`is_active=false`) tetiklenir | Değişmedi | Sonraki yenilemede veya yeniden yüklemede **geri döner** — güvenilir bir sandbox sıfırlaması değildir | | Sandbox hesabındaki aboneliği iptal et | Doğrudan değişiklik yok | Abonelik iptal edildi | Yenilemeler durur, mevcut dönem sona erdiğinde erişim biter ve test kullanıcısı ürünü yeniden satın alabilir | | Yeni bir Apple sandbox hesabıyla giriş yap | Yeni profil | Yeni, boş hesap | **Temiz** — tekrar test için önerilir | ### Bir test kullanıcısını temiz duruma sıfırlama \{#reset-a-tester-to-a-clean-state\} Tekrarlayan satın alma akışı testleri için profili sıfırlamak yerine her test için yeni bir Apple sandbox hesabı kullanın. Hesabı oluşturmak için [1. Adım'ı](#step-1-create-sandbox-test-account-in-app-store-connect), cihazda hesaba geçmek için ise [4. Adım'ı](#step-4-switch-to-sandbox-test-account) takip edin. Mevcut bir sandbox hesabını yeniden kullanıyorsanız önce [satın alma geçmişini temizleyin](#step-5-clear-purchase-history) — Adapty profilini silmek bunu temizlemez. ### Mevcut bir test kullanıcısının erişimini kaldırma \{#remove-access-from-an-existing-tester\} Bir test kullanıcısının erişimini kaldırmak için bitiş tarihini geriye almayın ya da Revoke access level API'ını çağırmayın. Sandbox ortamında abonelik her birkaç dakikada bir otomatik yenilenir. Her yenileme, aynı işlem zincirinde ilerleyen bir bitiş tarihi ayarlar; bu nedenle erişim kendiliğinden geri gelir. Revoke access level API bir `access_level_updated` (`is_active=false`) olayı tetikler, ancak bir sonraki yenileme bunu geçersiz kılar. Erişimi gerçekten durdurmak için aboneliği mağaza tarafında iptal etmeniz gerekir. Test cihazında **Settings > Developer > Sandbox Apple Account** yolunu izleyin, **Manage** seçeneğine tıklayın ve aboneliği iptal edin. Yenilemeler durur ve mevcut dönem sona erdiğinde erişim de biter. ### Profili silmek neden erişimi geri getiriyor \{#why-deleting-the-profile-brings-access-back\} Bir test kullanıcısı uygulamayı yeniden yüklediğinde, Adapty sandbox hesabının satın alma geçmişini alır ve yeni yüklemeyi mevcut satın almayla ilişkilendirir. Satın alma, sildiğiniz profile değil, mağaza hesabına bağlıdır. - **Anonim profiller**: `customer_user_id` olmadan yapılan bir yeniden yükleme, [ücretli erişim paylaşımı](sharing-paid-access-between-user-accounts) ayarınızdan bağımsız olarak her zaman mağaza hesabının access level'ını devralır. - **Tanımlı profiller**: Erişimin yeni bir `customer_user_id`'ye aktarılıp aktarılmayacağı, ücretli erişim paylaşımı ayarınıza bağlıdır. Adapty'nin bu profilleri nasıl bir zincire bağladığını öğrenmek için bkz. [Profiller nasıl çalışır](how-profiles-work#parent-and-inheritor-profiles). ## Abonelikleri test etme \{#test-subscriptions\} Sandbox test hesabı kullanarak uygulamayı test ederken, sandbox ortamında her test kullanıcısı için abonelik yenileme hızını ayarlayabilirsiniz. Abonelik yenileme hızlarını düzenleme hakkında daha fazla bilgi için [Apple'ın resmi belgelerine](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings) bakın. Varsayılan olarak, abonelikler aşağıdaki programa göre durmadan önce 12 kez yenilenir: | Abonelik süresi | 1 hafta | 1 ay | 2 ay | 3 ay | 6 ay | 1 yıl | | :----------------------------- | :--------- | :--------- | :--------- | :--------- | :--------- | :--------- | | Abonelik yenileme hızı | 3 dakika | 5 dakika | 10 dakika | 15 dakika | 30 dakika | 1 saat | | Fatura Yeniden Deneme süresi | 10 dakika | 10 dakika | 10 dakika | 10 dakika | 10 dakika | 10 dakika | | Fatura Ek Süre uzunluğu | 3 dakika | 5 dakika | 5 dakika | 5 dakika | 5 dakika | 5 dakika | :::note Test işlemlerinin [Olay akışı](validate-test-purchases)'nda görünmesi 10 dakikaya kadar sürebileceğini unutmayın. ::: Yenileme, ödeme yeniden denemesi ve ek süre gibi durumların uygulamanız ve backend'iniz tarafından doğru işlendiğini doğrulamak için sandbox'ı kullanın; üretim yenileme zamanlamasını tahmin etmek için değil. Yukarıdaki hızlandırılmış ve sınırlı zamanlama, üretim ortamıyla örtüşmez. Backend testleri için işlemleri sunucunuzda yeniden oynatmak istiyorsanız [Set transaction API](api-adapty/operations/setTransaction)'yi kullanabilirsiniz. ## Teklifleri test etme \{#test-offers\} Teklifleri test etmek için, uygunluk kontrolünün doğru çalışması amacıyla tüm kullanıcı makbuzlarının silinmesi gerekir. Teklifleri test etmenin en güvenilir yolu, tamamen yeni bir [Sandbox test hesabı](#step-1-create-sandbox-test-account-in-app-store-connect) kullanmaktır. Aynı Sandbox test hesabıyla tekrarlanan testler beklenmedik davranışlara yol açabilir. :::danger Aynı Sandbox test hesabıyla tekrar test yapıyorsanız, uygunlukla ilgili sorunları önlemek için [satın alma geçmişini temizlediğinizden](#step-5-clear-purchase-history) emin olun. ::: --- # File: local-sk-files --- --- title: "Xcode'da StoreKit testi" description: "İşlemlerin sorunsuz gerçekleştiğini doğrulamak için sandbox ortamında satın almaları test edin." --- Xcode'da StoreKit testi, sandbox hesabı oluşturmadan uygulama içi satın almaları yerel olarak test etmenizi sağlar. Bu tür bir test için şunları yapmanız gerekir: 1. [Adapty'de bir ürün oluşturun](quickstart-products) ve ona bir **App Store product ID** atayın. 2. Xcode'da yerel bir [StoreKit yapılandırma dosyası](https://developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode) oluşturun ve içine bir ürün ekleyin. Ürün ID'si, Adapty'deki **App Store product ID** ile aynı olmalıdır. 3. StoreKit yapılandırma dosyasını derleme şemanıza ekleyin ve uygulamayı derleyin. Emülatörde veya cihazınızda başlatın. ## Xcode'da StoreKit testini kullanmalı mıyım? \{#should-i-use-storekit-testing-in-xcode\} Bu test yöntemi, derlemeleri hızlıca test etmek veya Xcode özelliklerini kullanarak farklı satın alma senaryolarını denemek isteyen uygulama geliştiricileri için en kullanışlı seçenektir. Ancak bu testin yerel olduğunu unutmayın; yapılan değişiklikler Adapty Kontrol Paneli'nde görünmez. Uygulamanızı üretim ortamında yayınlamadan önce, [sandbox ortamını](test-purchases-in-sandbox) kullanarak [profiller ile çalışmayı](ios-quickstart-identify) test etmenizi öneririz. StoreKit testini **kullanmalısınız** eğer: - Satın alma mantığını test etmek istiyorsanız - Xcode araçlarıyla farklı satın alma senaryolarını yeniden oluşturmak istiyorsanız (ör. iptal edilen ödeme veya iade) - Emülatörde test etmek istiyorsanız StoreKit testini **kullanmamalısınız** eğer: - Profil ile ilgili mantığı test etmek istiyorsanız - Uygulamadaki işlemlerinizin Adapty Kontrol Paneli'nde görünüp görünmediğini kontrol etmek istiyorsanız - Uygulamanızı geliştirme ekibi dışındaki kişilerle test için paylaşmak istiyorsanız ## 1. Adım. StoreKit yapılandırma dosyası oluşturun \{#step-1-create-a-storekit-configuration-file\} Xcode'da StoreKit yapılandırma dosyası oluşturmak için: 1. **File > New > File from template** seçeneğine tıklayın. Ardından **StoreKit Configuration File**'ı seçin ve **Next**'e tıklayın. 2. Bir isim verin. Ardından, ürünlerin App Store Connect'te olup olmadığına göre: - **Sync this file with an app in App Store Connect** seçeneğini seçin: Tüm App Store Connect ürünlerini içeren ve yerel olarak test edebileceğiniz bir yapılandırma dosyası oluşturmak için. - **Sync this file with an app in App Store Connect** seçeneğini seçmeyin: Ürünleri manuel olarak ekleyeceğiniz boş bir yapılandırma dosyası oluşturmak için. **Next**'e tıklayın. 3. Uygulamanızı hedef olarak eklemeyin, devam edin. App Store Connect'ten senkronize edilmiş ürünlerle çalışıyorsanız [2. Adım](#step-2-add-the-configuration-file-to-the-build-scheme)'a geçin. 4. Ürünleriniz App Store Connect'ten senkronize edilmemişse sol alttaki **+** simgesine tıklayın ve bir ürün türü seçin. 5. Bir abonelik grubu adı girin ve **Next**'e tıklayın. 6. Bir referans adı girin. **Product ID** alanına Adapty'deki ürününüzün **App Store product ID**'sini girin. 7. Yapılandırma dosyasında fiyatlandırma, teklif ve diğer ürün ayarlarını yapılandırın. Ya da daha fazla ürün ekleyin. ## 2. Adım. Yapılandırma dosyasını derleme şemasına ekleyin \{#step-2-add-the-configuration-file-to-the-build-scheme\} Uygulamayı bu yapılandırma dosyasıyla derlemek için dosyayı bir derleme şemasına eklemeniz gerekir. Test ve üretim şemalarını ayırmak en iyi uygulamadır, bu nedenle test için yeni bir şema oluşturmanızı öneririz: 1. Üstteki uygulama adınıza tıklayın ve **New scheme**'i seçin. 2. Şema için bir isim girin ve **OK**'a tıklayın. 3. Uygulama adına tekrar tıklayın ve **Edit scheme**'i seçin. **StoreKit configuration** bölümünde, derleme sırasında kullanılacak yerel yapılandırma dosyanızı seçin. ## 3. Adım. Derle ve test et \{#step-3-build--test\} Artık App Store arka ucuna bağlanmadan uygulamayı derleyip uygulama içi satın almaları test edebilirsiniz. Yerel olarak ürün satın alabilir ve access level'lara erişebilirsiniz. Bu değişiklikler Adapty Kontrol Paneli'ne yansımaz, ancak ücretli özelliklerin kilidini yerel olarak açmayı yine de test edebilirsiniz. Xcode'da StoreKit testi ile kullanılabilen diğer özellikler hakkında [daha fazla bilgi edinin](https://developer.apple.com/documentation/xcode/testing-in-app-purchases-with-storekit-transaction-manager-in-code). --- # File: testing-on-android --- --- title: "Google Play Store'da uygulama içi satın almaları test edin" description: "Adapty kullanarak Android'de abonelik satın almalarını test edin." --- Android uygulamanızdaki uygulama içi satın almaları (IAP) halka açık bir sürüm yayınlamadan önce test etmek kritik bir adımdır. Sandbox testi, kullanıcılarınızdan gerçek para almadan IAP'leri güvenli ve verimli biçimde test etmenin en iyi yoludur. Bu kılavuzda, Android için Google Play Store'da IAP'lerin sandbox ortamında nasıl test edileceğini adım adım anlatacağız. :::note **Sandbox işlemleri tüm analitik grafiklerden hariç tutulur.** Yine de bireysel profil sayfalarında ve etkinlik akışında görünürler. ::: ## Test ortamı \{#testing-environment\} Android uygulamanızın en iyi performansı göstermesi için emülatör yerine gerçek bir cihazda test etmenizi öneririz. Emülatörlerde başarılı testler yapsak da Google, gerçek cihaz kullanımını tavsiye ediyor. Emülatör kullanmaya karar verirseniz, Google Play'in kurulu olduğundan emin olun. Bu, uygulamanızın düzgün çalıştığını doğrulamanıza yardımcı olur. ## 1. Uygulama testi için test hesabı oluşturun \{#set-up-test-account-for-app-testing\} Geliştirmenin sonraki aşamalarında testleri kolaylaştırmak için uygulama içi satın alma testlerinde kullanacağınız bir test kullanıcısı oluşturmanız gerekiyor. Bu kullanıcı, Android test cihazınızda ilk oturum açacağınız hesap olacak. Android cihazlarda birincil hesabın yalnızca fabrika sıfırlamasıyla değiştirilebildiğini unutmayın; bu işlem tüm verilerinizi siler. Bu nedenle, fabrika sıfırlamasına gerek kalmamak için test kullanıcı hesabınızı baştan doğru şekilde ayarlamanız önemlidir. :::important Test hesabını nasıl oluşturacağınız, kullandığınız cihaza bağlıdır: - Yalnızca test amacıyla kullandığınız bir cihazınız varsa, **ayrı bir test hesabı (yeni bir Gmail hesabı)** oluşturun. - Böyle bir cihazınız yoksa, **kişisel hesabınızı** kullanıp geçici olarak **License testing** özelliğini etkinleştirebilirsiniz. - Hiç Android cihazınız yoksa, **ayrı bir test hesabı oluşturup emülatörle kullanabilirsiniz**. Ancak bu yöntem, gerçek cihaza özgü sorunları yakalamanıza izin vermediğinden önerilmez. ::: ## 2. Lisans testini etkinleştir \{#enable-license-testing\} Test kullanıcı hesabını oluşturduktan sonra, uygulamanız için lisans testini yapılandırmanız gerekecek. Bunun için şu adımları izleyin: 1. Google Play Console kenar çubuğunda **Settings** bölümüne gidin ve **Monetization** altındaki **License testing** seçeneğini seçin. <img src="/assets/shared/img/android-license-testing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Mevcut bir lisans test kullanıcıları listesi seçin veya yeni bir tane oluşturun. <img src="/assets/shared/img/android-testers.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Test için kullanacağınız hesabı listeye ekleyin ve değişiklikleri kaydedin. Ekip üyelerinizin de uygulamayı test etmesi gerekiyorsa e-posta adreslerini listeye ekleyebilirsiniz; böylece tüm gruba erişim sağlanmış olur. <img src="/assets/shared/img/android-list.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 3. Kapalı iz oluşturun ve test hesabı ekleyin \{#3-create-closed-track-and-add-test-account-to-it\} Teste başlamak için uygulamanızın imzalı bir sürümünü kapalı bir ize yayımlamanız gerekir: 1. Uygulamanızı açın ve menüden **Test and release > Testing > Closed testing** seçeneğine gidin. Ardından **Create track** butonuna tıklayın. <img src="/assets/shared/img/android-closed-testing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Kapalı test track adını girin ve **Create track** düğmesine tıklayın. 3. Track'e bir test kullanıcısı listesi ekleyin. 4. **How testers join your test** bölümünden bağlantıyı kopyalayın ve test hesabıyla oturum açılmış cihaza gönderin. Kullanıcıyı tester yapmak için bağlantıyı test cihazınızda açın. <img src="/assets/shared/img/android-link.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning Başarılı bir test süreci için aşağıdakileri göz önünde bulundurun: - Opt-in URL'sini açmak, Play hesabınızı test için işaretler. Bu adımı tamamlamazsanız ürünler yüklenmez. - Geliştiriciler çoğu zaman test derlemeleri için farklı bir uygulama kimliği (application ID) kullanır. Google Play Hizmetleri, uygulama içi satın almaları bulmak için uygulama kimliğini kullandığından bu durum sorunlara yol açabilir. - Test cihazında PIN yoksa, test kullanıcısının consumable ürünleri satın almasına izin verilirken aboneliklere izin verilmediği durumlar olabilir. Bu durum, anlaşılması güç bir "Something went wrong" mesajı olarak kendini gösterebilir. Test cihazında PIN bulunduğundan ve cihazın Google Play Store'a giriş yapmış olduğundan emin olun. ::: ## 4. İmzalı APK'yı kapalı kanala yükleyin \{#4-upload-a-signed-apk-to-the-closed-track\} İmzalı bir APK oluşturun veya Android App Bundle kullanarak az önce oluşturduğunuz kapalı kanala imzalı APK'yı yükleyin. Sürümü yayına almanıza bile gerek yok. Sadece APK'yı yükleyin. Bu konuda daha fazla bilgiye [bu](https://support.google.com/googleplay/android-developer/answer/9859348?visit_id=638929100639477968-3849460621&rd=1) destek makalesinden ulaşabilirsiniz. :::important Uygulamanız yeniyse, ülkenizde veya bölgenizde kullanılabilir hale getirmeniz gerekebilir. Bunun için **Testing > Closed testing** bölümüne gidin, test track'inize tıklayın ve **Countries/regions** kısmından istediğiniz ülke ve bölgeleri ekleyin. ::: ## 5. Uygulama içi satın almaları test etme \{#5-test-in-app-purchases\} APK'yı yükledikten sonra sürümün işlenmesi için birkaç dakika bekleyin. Ardından test cihazınızı açın ve Testers listesine eklediğiniz e-posta hesabıyla oturum açın. Artık üretim uygulamasında olduğu gibi uygulama içi satın almaları test edebilirsiniz. <img src="/assets/shared/img/a8d2da9-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Daha fazlası \{#read-more\} Android uygulamalarında uygulama içi satın almaları test etme hakkında daha fazla bilgi edinmek için şu kaynaklara göz atın: - [Sandbox'ta yenileme süreleri](https://developer.android.com/google/play/billing/test#subs) - [Tek seferlik satın almaları test etme](https://developer.android.com/google/play/billing/test#one-time) --- # File: validate-test-purchases --- --- title: "Test satın alımları doğrulama" description: "Sorunsuz işlemler için Adapty'de test satın alımlarını doğrulayın." --- Mobil uygulamanızı production'a almadan önce uygulama içi satın alımları kapsamlı şekilde test etmek kritik önem taşır. Ayrıntılı rehberlik için [Apple App Store'da uygulama içi satın alımları test etme](test-purchases-in-sandbox) ve [Google Play Store'da uygulama içi satın alımları test etme](testing-on-android) konularına bakabilirsiniz. Testlere başladıktan sonra test satın alımlarının başarılı olup olmadığını doğrulamanız gerekir. Mobil cihazınızda her test satın alımı yaptığınızda, ilgili işlemi Adapty Kontrol Paneli'ndeki [**Event Feed**](https://app.adapty.io/event-feed) üzerinden kontrol edin. Satın alım **Event Feed**'de görünmüyorsa Adapty tarafından takip edilmiyor demektir. ## Test satın alımı başarılı \{#test-purchase-is-successful\} Test satın alımı başarılıysa işlem eventi **Event Feed**'de görüntülenir: <img src="/assets/shared/img/9ade2d5-event_feed_sandbox.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> İşlemler beklendiği gibi çalışıyorsa [Yayın kontrol listesi](release-checklist)'ne geçin ve ardından uygulamayı yayınlayın. ## Test satın alımı başarısız \{#test-purchase-is-not-successful\} 10 dakika içinde herhangi bir işlem eventi görmüyorsanız veya mobil uygulamada bir hatayla karşılaşıyorsanız olası çözümler için [Sorun Giderme](troubleshooting-test-purchases) ve hata işleme makalelerine bakın: [iOS için](ios-sdk-error-handling), [Android için](android-sdk-error-handling), [React Native için](react-native-handle-errors), [Flutter için](error-handling-on-flutter-react-native-unity), [Unity için](unity-handle-errors) ve [Kotlin Multiplatform](kmp-handle-errors). <img src="/assets/shared/img/31a79b2-no_events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: troubleshooting-test-purchases --- --- title: "Test satın alımlarında sorun giderme" description: "Adapty'de test satın alımlarında sorun giderin ve yaygın uygulama içi işlem sorunlarını çözün." --- İşlem sorunlarıyla karşılaşırsanız, lütfen önce [yayın kontrol listesi](release-checklist)'nde belirtilen tüm adımları tamamladığınızdan emin olun. Tüm adımları tamamladıktan sonra hâlâ sorun yaşıyorsanız, çözmek için aşağıdaki yönergeleri izleyin: ## Mobil uygulamada hata döndürülüyor \{#an-error-is-returned-in-the-mobile-app\} Platformunuza ait hata listesine bakın: [iOS için](ios-sdk-error-handling), [Android için](android-sdk-error-handling), [React Native için](react-native-troubleshoot-purchases), [Flutter](error-handling-on-flutter-react-native-unity) ve [Unity](unity-troubleshoot-purchases); ardından sorunu çözmek için önerilerimizi izleyin. ## Mobil uygulamada hata döndürülmediği hâlde işlem Event Feed'de görünmüyor \{#transaction-is-absent-from-the-event-feed-although-no-error-is-returned-in-the-mobile-app\} Bu sorunu çözmek için aşağıdakileri kontrol edin: 1. **iOS için**: Simülatör yerine gerçek bir cihaz kullandığınızdan emin olun. 2. Uygulamanızın `Bundle ID`/`Package name` değerinin [**App settings**](https://app.adapty.io/settings/general) bölümündeki değerle eşleştiğinden emin olun. 3. Uygulamanızdaki `PUBLIC_SDK_KEY` değerinin Adapty Kontrol Paneli'ndeki **Public SDK key** ile eşleştiğinden emin olun: [**App settings** -> **General** sekmesi -> **API keys** bölümü](https://app.adapty.io/settings/general). 4. Sandbox hesabı kullandığınızdan emin olun; [yerel StoreKit yapılandırma dosyası](local-sk-files) kullanmıyor olmalısınız. Daha önce test için yerel StoreKit yapılandırma dosyası kullandıysanız, mevcut derlemenizde bunu kullanmadığınızdan emin olun. ## Test profilimde hiç etkinlik yok \{#no-event-is-present-in-my-testing-profile\} Bu normal bir davranıştır. Adapty'de yeni bir kullanıcı profili kaydı otomatik olarak şu durumlarda oluşturulur: - Bir kullanıcı uygulamanızı ilk kez çalıştırdığında - Bir kullanıcı uygulamanızdan çıkış yaptığında **Bu neden olur:** Tüm işlemler ve etkinlikler, ilk işlemi gerçekleştiren profile bağlıdır. Bu sayede işlem geçmişinin tamamı (denemeler, satın alımlar, yenilemeler) aynı profile bağlı kalır. **Ne görürsünüz:** Etkinlik içermeyen yeni profil kayıtları ("orijinal olmayan profiller" olarak adlandırılır) görünebilir; ancak bu profiller access level bilgisini korur. `access_level_updated` etkinliklerini görebilirsiniz. Bu beklenen bir davranıştır. **Test için:** Birden fazla profil oluşmaması adına, uygulamayı her yeniden yüklediğinizde yeni bir test hesabı (Sandbox Apple ID) oluşturun. Daha fazla ayrıntı için [Profil oluşturma](how-profiles-work#profile-creation) bölümüne bakın. Aşağıda orijinal olmayan bir profile örneği verilmiştir. **User history** bölümünde etkinlik olmadığına ve access level'ın mevcut olduğuna dikkat edin. <img src="/assets/shared/img/98d0dad-non-original_profile.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Fiyatlar App Store Connect'te belirlenen gerçek fiyatları yansıtmıyor \{#prices-do-not-reflect-the-actual-prices-set-in-app-store-connect\} Uygulama içi satın alımlar için sandbox ortamını kullanan Sandbox ve TestFlight'ta, fiyatların doğruluğuna odaklanmak yerine satın alma akışının doğru çalışıp çalışmadığını doğrulamak önemlidir. Apple'ın API'sinin, özellikle cihazlar veya hesaplar için farklı bölgeler yapılandırıldığında zaman zaman hatalı veriler sağlayabileceğini belirtmek gerekir. Fiyatlar doğrudan Store'dan geldiğinden ve Adapty arka ucu satın alma fiyatlarını hiçbir şekilde etkilemediğinden, Adapty üzerinden yapılan satın alma testlerinde fiyat tutarsızlıklarını görmezden gelebilirsiniz. Bu nedenle, satın alma akışının amaçlandığı gibi çalıştığından emin olmak için fiyatların doğruluğundan ziyade akışın kendisini test etmeye öncelik verin. ## Event Feed'deki işlem zamanı hatalı \{#the-transaction-time-in-the-event-feed-is-incorrect\} **Event Feed**, **App Settings** bölümünde ayarlanan saat dilimini kullanır. Etkinliklerin saat dilimini yerel saatinizle uyumlu hale getirmek için [**App settings** -> **General** sekmesi](https://app.adapty.io/settings/general) bölümünden **Reporting timezone** ayarını düzenleyin. ## Paywall'lar ve ürünler yüklenirken çok uzun sürüyor \{#paywalls-and-products-take-a-long-time-to-load\} Bu sorun, test hesabınızın uzun bir işlem geçmişine sahip olması durumunda ortaya çıkabilir. [App Store Connect'te Sandbox Test Hesabı (Sandbox Apple ID) Oluşturma](test-purchases-in-sandbox#step-1-create-sandbox-test-account-in-app-store-connect) bölümünde açıklandığı gibi her seferinde yeni bir test hesabı oluşturmanızı kesinlikle öneririz. Yeni bir hesap oluşturamıyorsanız, iOS cihazınızda aşağıdaki adımları izleyerek mevcut hesabınızdaki işlem geçmişini temizleyebilirsiniz: 1. **Settings** uygulamasını açın ve **App Store**'a dokunun. 2. **Sandbox Apple ID**'nize dokunun. 3. Açılan pencerede **Manage**'i seçin. 4. **Account Settings** sayfasında **Clear Purchase History**'ye dokunun. Daha fazla ayrıntı için [Apple Developer belgelerine](https://developer.apple.com/documentation/storekit/testing-in-app-purchases-with-sandbox) bakın. --- # File: test-devices --- --- title: "Test cihazları" description: "Verimli uygulama testi için Adapty'de test cihazlarını nasıl yöneteceğinizi öğrenin." --- Test amacıyla cihazınızı bir test cihazı olarak tanımlayabilirsiniz; bu sayede önbelleğe alma devre dışı kalır ve yaptığınız değişiklikler anında yansıtılır. :::note Test cihazları belirli SDK sürümlerinden itibaren desteklenmektedir: - iOS: 2.11.1 - Android: 2.11.3 - React Native: 2.11.1 Flutter ve Unity desteği daha sonra eklenecektir. ::: ## Cihazınızı test cihazı olarak işaretleyin \{#mark-your-device-as-test\} 1. Adapty Kontrol Paneli'nde [**App settings**](https://app.adapty.io/settings/general) bölümünü açın. 2. **General** sekmesinde **Test devices** bölümüne kadar aşağı kaydırın. <img src="/assets/shared/img/14c581d-test_device_add.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Add test device** düğmesine tıklayın. <img src="/assets/shared/img/f86d5e2-test_users_add_device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Add test device** penceresinde şu bilgileri girin: | Alan | Açıklama | |:----------------------------------------------| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Test device name** | Başvurunuz için test cihazının/cihazlarının adı. | | **ID used to identify this test device** | Test cihazını/cihazlarını tanımlamak için kullanmayı planladığınız tanımlayıcı türünü seçin. En iyi seçeneği belirlemek için aşağıdaki [Hangi tanımlayıcıyı kullanmalısınız](test-devices#which-identifier-you-should-use) bölümündeki önerilerimize bakın. | | **ID value** | Tanımlayıcının değerini girin. | 5. Değişiklikleri kaydetmek için **Add test device** düğmesine tıklamayı unutmayın. ## Hangi tanımlayıcıyı kullanmalısınız \{#which-identifier-you-should-use\} Bir cihazı tanımlamak için birden fazla tanımlayıcı kullanabilirsiniz. Şu seçenekleri öneriyoruz: - <InlineTooltip tooltip="identify your users in Adapty">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip> kullanıcılarınızı Adapty'de tanımlıyorsanız hem iOS hem de Android cihazlar için **Customer User ID** en iyi seçenektir. Özellikle uygulamanızda bir hesap için birden fazla test cihazınız varsa bu tercih idealdir. **ID used to identify this test device** olarak Customer User ID kullanıldığında, bu hesaba bağlı tüm cihazlar test cihazı olarak işaretlenir. - **IDFA (iOS)** ve **Advertising ID (Android)**: Bu reklam tanımlayıcıları, kullanıcılarınızdan bunlara erişim için izin zaten istiyorsanız sırasıyla iOS ve Android cihazlar için mükemmel bir seçimdir. Customer User ID'niz olsa bile, test sırasında uygulamanızda hesap değiştiriyorsanız reklam tanımlayıcılarını tercih edebilirsiniz. Ayrıca aynı hesapta hem test hem de kişisel cihazlarınız varsa ve kişisel cihazların test cihazı olarak işaretlenmesini istemiyorsanız bu tanımlayıcılar işe yarar. Customer User ID, IDFA veya Advertising ID kullanamıyorsanız Adapty Profile ID, IDFV ve Android ID gibi daha az kullanışlı ancak yine de geçerli başka seçenekler de mevcuttur. Tüm olası seçenekleri ayrıntılı olarak inceleyelim. ### Tüm platformlar için tanımlayıcılar \{#identifiers-for-all-platforms\} | Tanımlayıcı | Kullanım | |----------|-----| | Customer User ID | <p>Kullanıcılarınızı kendi sisteminizde tanımlamak için sizin belirlediğiniz benzersiz bir tanımlayıcı. Bu, kullanıcının e-postası, dahili kimliğiniz veya herhangi bir metin olabilir. Bu seçeneği kullanmak için <InlineTooltip tooltip="Identify your users in Adapty">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip> kullanıcılarınızı tanımlamanız gerekir.</p><p></p><p>Özellikle aynı hesap için birden fazla cihaz kullanıyorsanız test cihazını tanımlamak için en iyi seçenektir. Bu hesaba sahip tüm cihazlar test cihazı olarak kabul edilir.</p> | | Adapty profile ID | <p>Adapty'deki [kullanıcı profili](profiles-crm) için benzersiz bir tanımlayıcı.</p><p></p><p>iOS için Customer User ID veya IDFA, Android için Advertising ID kullanamıyorsanız bunu kullanın. Adapty Profile ID'nin uygulamayı yeniden yüklerseniz veya yeniden giriş yaparsanız değişebileceğini unutmayın.</p> | #### Customer User ID ve Adapty profile ID nasıl edinilir \{#how-to-obtain-customer-user-id-and-adapty-profile-id\} Her iki tanımlayıcı da Adapty Kontrol Paneli'ndeki **Profile** ayrıntılarından edinilebilir: 1. Kullanıcının profilini [**Adapty Profiles** -> **Event feed** sekmesinde](https://app.adapty.io/event-feed) bulun. :::note Tam profili bulmak için nadir bir işlem türü gerçekleştirin. Bu durumda işlem [**Event Feed**](https://app.adapty.io/event-feed) içinde göründüğünde kolayca tespit edebilirsiniz. ::: 2. Profil ayrıntılarındaki **Customer user ID** ve **Adapty ID** alan değerlerini kopyalayın: <img src="/assets/shared/img/345d308-test_users_CUID_adapty_ID.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Apple tanımlayıcıları \{#apple-identifiers\} | Tanımlayıcı | Kullanım | |----------|-----| | IDFA | <p>Identifier for Advertisers (IDFA), Apple'ın bir kullanıcının cihazına atadığı benzersiz bir cihaz tanımlayıcısıdır.</p><p></p><p>Kendi kendine hiçbir zaman değişmediğinden (manuel olarak sıfırlayabilseniz de) iOS cihazlar için idealdir.</p><p>**Not**: iOS 14.5'in yayımlanmasıyla birlikte reklamverenler IDFA'ya erişmek için kullanıcı onayı istemek zorundadır. Uygulamanızda onay istediğinizden ve test cihazınızda onay verdiğinizden emin olun.</p> | | IDFV | Identifier for Vendors (IDFV), Apple'ın aynı yayıncıya/satıcıya ait tüm uygulamalar için tek bir cihazdaki her uygulamaya atadığı benzersiz bir alfanümerik tanımlayıcıdır. Uygulamayı yeniden yüklerseniz veya güncellerseniz değişebilir. | #### IDFA nasıl edinilir \{#how-to-obtain-the-idfa\} Apple, IDFA'yı varsayılan olarak sağlamaz. Adapty Kontrol Paneli'ndeki profil attribution bilgilerinden edinin: 1. Kullanıcının profilini [**Adapty Profiles** -> **Event feed** sekmesinde](https://app.adapty.io/event-feed) bulun. :::note Tam profili bulmak için nadir bir işlem türü gerçekleştirin. Bu durumda işlem [**Event Feed**](https://app.adapty.io/event-feed) içinde göründüğünde kolayca tespit edebilirsiniz. ::: 2. Profil ayrıntılarını açın ve **Attributes** bölümündeki **IDFA** alan değerini kopyalayın: <img src="/assets/shared/img/ce4a63f-test_users_idfa.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Alternatif olarak, [IDFA'nızı size gösterecek uygulamayı App Store'da bulabilirsiniz](https://www.apple.com/us/search/idfa?src=globalnav). #### Identifier for Vendors (IDFV) nasıl edinilir \{#how-to-obtain-the-identifier-for-vendors-idfv\} IDFV'yi edinmek için geliştiricinizdeki aşağıdaki yöntemi uygulamanız için kullanmasını ve alınan tanımlayıcıyı loglarınıza veya debug panelinize yansıtmasını isteyin. ```swift showLineNumbers title="Swift" UIDevice.current.identifierForVendor ``` ### Google tanımlayıcıları \{#google-identifiers\} | Tanımlayıcı | Kullanım | |----------|-----| | Advertising ID | <p>Advertising ID, Google'ın bir kullanıcının cihazına atadığı benzersiz bir cihaz tanımlayıcısıdır.</p><p>Kendi kendine hiçbir zaman değişmediğinden (manuel olarak sıfırlayabilseniz de) Android cihazlar için idealdir.</p><p>**Not**: Kullanmak için Android 12 veya üzerini kullanıyorsanız **Ads** ayarlarınızdaki **Opt out of Ads Personalization** seçeneğini kapatın.</p>| | Android ID | Android ID, uygulama imzalama anahtarı, kullanıcı ve cihazın her kombinasyonu için benzersiz bir tanımlayıcıdır. Android 8.0 ve üzeri sürümlerde kullanılabilir. | #### Advertising ID nasıl edinilir \{#how-to-obtain-advertising-id\} Cihazınızın reklam kimliğini bulmak için: 1. Android cihazınızda **Settings** uygulamasını açın. 2. **Google** seçeneğine tıklayın. 3. **Services** altında **Ads** seçeneğini seçin. Reklam kimliğiniz ekranın alt kısmında listelenecektir. #### Android ID nasıl edinilir \{#how-to-obtain-android-id\} Android ID'yi edinmek için geliştiricinizdeki [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) değerini uygulamanız için aşağıdaki yöntemi kullanarak istemesini ve alınan tanımlayıcıyı loglarınıza veya debug panelinize yansıtmasını isteyin. ```kotlin showLineNumbers title="Kotlin/Java" android.provider.Settings.Secure.getString(contentResolver, android.provider.Settings.Secure.ANDROID_ID); ``` --- # File: release-checklist --- --- title: "Yayın kontrol listesi" description: "Adapty'nin yayın kontrol listesini takip ederek uygulama güncelleme sürecinizin sorunsuz geçmesini sağlayın." --- Adapty'yi tercih ettiğiniz için çok mutluyuz! Umarız entegrasyon süreci sorunsuz geçmiştir. Bu kılavuz, uygulamanızı mağazalarda yayınlamaya hazırlamak ve monetizasyon akışının düzgün çalıştığından emin olmak için izlemeniz gereken adımları açıklar. ## Başlamadan önce gerekenler \{#pre-flight-essentials\} Doğrulamaya başlamadan önce şunlara ihtiyacınız var: - Sandbox hesabı olan gerçek bir cihaz - Adapty Kontrol Paneli'ne erişim - App Store Connect / Google Play Console'a erişim :::note Sandbox satın almaları simülatörlerde çalışabilse de ödeme diyalogları ve biyometrik doğrulama gibi tüm akışları test etmek için gerçek cihaz gereklidir. ::: <Button id="test-purchases-in-sandbox"> App Store için test kılavuzu </Button> <Button id="testing-on-android"> Google Play için test kılavuzu </Button> ## Genel doğrulamalar \{#universal-validations\} - [ ] **Mağaza bağlantısı**: Adapty'yi App Store ve/veya Google Play'e bağladığınızdan emin olun: - [ ] [App Store](initial_ios) - [ ] [Google Play](initial-android) - [ ] **Abonelik olay iletimi**: Sunucu bildirimlerinin yapılandırıldığını doğrulayın: - [ ] [App Store sunucu bildirimleri](enable-app-store-server-notifications) - [ ] [Gerçek zamanlı geliştirici bildirimleri (RTDN)](enable-real-time-developer-notifications-rtdn) - [ ] **Profil tanımlama**: Kullanıcı tanımlama mantığını doğrulayın ve satın almaların doğru profile eşlendiğinden emin olun: - [ ] [Uygulama kodunuzdaki tanımlama mantığının kullanım senaryonuzla uyuştuğunu kontrol edin](ios-quickstart-identify) - [ ] [Kullanıcı profilleri arasında ücretli erişim paylaşımı için üst/mirasçı mantığını anladığınızdan emin olun](sharing-paid-access-between-user-accounts) - [ ] **Teklifler**: Uygulamanızda App Store promosyon teklifleri kullanıyorsanız, [Uygulama içi satın alma anahtarını](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) hem ana alana hem de **App Store promotional offers** bölümüne eklediğinizden emin olun. - [ ] **Veri toplama**: Gizlilik uyumluluğunu sağlayın: - [ ] GDPR veya CCPA gibi gizlilik düzenlemelerine uymak zorundaysanız ya da uygulamanız çocuklara yönelikse, [IDFA ve IP toplama ile paylaşımını etkinleştirip etkinleştirmeyeceğinizi](sdk-installation-ios#data-policies) belirleyin. - [ ] Uygulamanız AppTrackingTransparency kullanıyorsa, [yetkilendirme durumunu Adapty'ye gönderdiğinizden](ios-deal-with-att) emin olun. - [ ] **Gizlilik etiketleri**: Adapty'nin topladığı veriler ve inceleme için hangi işaretleri ayarlamanız gerektiği hakkında [daha fazla bilgi edinin](apple-app-privacy). ## Satın alma doğrulamaları \{#purchase-validations\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Yayına geçmeden önce, uygulamanızdaki satın almaların düzgün çalıştığından ve paywallınızın mağaza incelemesine hazır olduğundan emin olun. Uygulama içi satın almaları doğrulama yönteminiz, bunları nasıl uyguladığınıza bağlıdır: - Adapty Paywall Builder'da oluşturulmuş bir paywall gösteriyorsunuz - Kendi paywallınızı uyguladınız ve satın almaları yönetmek için içinde `makePurchase` metodunu kullanıyorsunuz - Adapty'yi gözlemci modunda kullanıyorsunuz (Adapty Paywall Builder veya özel paywallınızla) <Tabs groupId="paywall" queryString> <TabItem value="builder" label="Adapty Paywall Builder" default> **Hedef**: Adapty paywallı render eder, kullanıcılar ürün satın alabilir, erişim açılır ve geri yükleme akışı çalışır. - [ ] Uygulamanız, yayınlayacağınız aynı placement'tan [paywallı gösteriyor](ios-present-paywalls). - [ ] Paywall ekranda görüntüleniyor. Yükleme çok uzun sürüyorsa (örneğin, kararsız internet bağlantısı durumunda), [getirme politikanızı ayarlamayı](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) düşünün. - [ ] Paywall beklenen varyantla eşleşiyor (varsa kitle/yerel ayar). Gerekirse [kitle önceliğini değiştirebilirsiniz](change-audience-priority). - [ ] Ürünler ve fiyatlar paywall'da görünüyor. Apple'ın API'sinin test sırasında (özellikle farklı bölge yapılandırmalarında) zaman zaman yanlış fiyatlar verebileceğini unutmayın; Adapty mağaza fiyatlarını etkilemediğinden fiyat doğruluğu yerine satın alma akışı işlevselliğini test etmeye öncelik verin. - [ ] Sandbox satın alması başarıyla tamamlanıyor. Başarılı satın alma geri araması alınıyor. - [ ] Erişim açılıyor ve devam ediyor. [Ücretli erişimin mevcut Adapty profiline göre verildiğini](ios-check-subscription-status#connect-profile-with-paywall-logic) doğrulayın. - [ ] Satın alma sonrasında Adapty profilinde aktif bir access level var. - [ ] Ücretli özellikler, profil söz konusu access level'ı içerdiğinde açılıyor (yalnızca satın alma geri aramasında değil). - [ ] Satın almaları geri yükleme çalışıyor. Uygulamayı yeniden yüklediğinizde veya yeni bir cihaza kurduğunuzda, otomatik satın alma geri yükleme [Ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ayarına göre çalışıyor. Herhangi bir arka uç kimlik doğrulamanız yoksa, satın almalar ayardan bağımsız olarak otomatik olarak geri yükleniyor. Diğer durumlarda, kullanıcıların uygulamayı yeniden yükledikten sonra satın almalarını geri yükleyebildiğinden emin olun. - [ ] Mağaza inceleme gereksinimleri: - [ ] **Restore purchases** düğmesi paywall'da mevcut. Bunu paywall builder'a ekleyebilirsiniz; tıklandığında satın alma geri yüklemelerini otomatik olarak işler. - [ ] Kullanım Koşulları ve Gizlilik Politikasına paywall ekranından erişilebiliyor ve bu bağlantılara tıklandığında tarayıcıda açılıyorlar. </TabItem> <TabItem value="makepurchase" label="Özel paywall (makePurchase)" default> **Hedef**: Siz UI'yi render ediyorsunuz; Adapty satın almaları, profil güncellemelerini ve geri yüklemeleri yönetiyor. - [ ] Ürün ID'leri uygulama kodunuza sabit olarak yazılmamış. Yalnızca [placement](placements) ID'lerini sabit olarak yazıyorsunuz. - [ ] Uygulamanız, yayına alacağınız aynı placement'tan [ürünleri çekiyor](fetch-paywalls-and-products). - [ ] Ürün listesi başarıyla yükleniyor. Yükleme çok uzun sürüyorsa (örneğin siz veya kullanıcılarınız dengesiz bir internet bağlantısıyla karşılaşıyorsanız), [fetch policy ayarlarını düzenlemeyi](fetch-paywalls-and-products#fetch-paywall-information) düşünebilirsiniz. - [ ] Çekilen ürünler, beklenen varyantla eşleşiyor (varsa kitle/dil ayarlarına göre). Gerekirse [kitle önceliğini değiştirebilirsiniz](change-audience-priority). - [ ] Ürünler ve fiyatlar paywall'da görünüyor. Apple'ın API'si, test sırasında zaman zaman yanlış fiyatlar döndürebilir (özellikle farklı bölge yapılandırmalarında); bu nedenle fiyat doğruluğu yerine satın alma akışının işlevselliğini test etmeye öncelik verin; Adapty, Store fiyatlarını etkilemez. - [ ] [makePurchase](making-purchases) ile yapılan sandbox satın alması başarıyla tamamlanıyor: - [ ] Başarılı satın alma sonucu işleniyor. - [ ] Beklemedeki/başarısız/iptal edilen durumlar sorunsuz şekilde ele alınıyor. - [ ] [Remote config kullanıyorsanız](present-remote-config-paywalls), değerleri paywall'unuza doğru şekilde çekiliyor. - [ ] Bir paywall gösterildiğinde [`logShowFlow` (iOS SDK v4+) / `logShowPaywall` metodu](present-remote-config-paywalls#track-paywall-view-events) çağrılıyor. - [ ] Sandbox satın alması başarıyla tamamlanıyor. Başarılı satın alma callback'i alınıyor. - [ ] Erişim kilidi açılıyor ve devam ediyor. [Mevcut Adapty profiline göre ücretli erişimin verildiğini](ios-check-subscription-status#connect-profile-with-paywall-logic) doğrulayın. - [ ] Satın alma sonrasında Adapty profilinde aktif bir access level bulunuyor. - [ ] Profil o access level'ı içerdiğinde ücretli özellikler kilidi açılıyor (yalnızca satın alma callback'ine bağlı kalmadan). - [ ] Satın almaları geri yükleme çalışıyor. Uygulamayı yeniden yüklerken veya yeni bir cihaza yüklerken, otomatik satın alma geri yükleme işlemi [Ücretli erişimi paylaşma](sharing-paid-access-between-user-accounts) ayarına göre çalışıyor. Herhangi bir backend kimlik doğrulamanız yoksa, satın almalar ayardan bağımsız olarak otomatik geri yükleniyor. Diğer durumlarda, kullanıcıların uygulamayı yeniden yükledikten sonra satın almalarını geri yükleyebildiğinden emin olun. - [ ] Store inceleme gereksinimleri: - [ ] **Restore purchases** düğmesine erişilebiliyor ve [geri yüklemeleri işliyor](restore-purchase). - [ ] Kullanım Koşulları ve Gizlilik Politikası, paywall ekranından erişilebilir durumda ve bu bağlantılara tıklandığında bir tarayıcıda açılıyorlar. </TabItem> <TabItem value="observer" label="Gözlemci modu"> **Hedef**: Satın almaları, profil güncellemelerini ve geri yüklemeleri kendiniz yönetiyorsunuz; Adapty işlem raporlamasını alıyor. - [ ] **Uygulamanız satın alma işlemlerini kendi satın alma akışınızla tamamlıyor** (StoreKit / BillingClient / backend): - [ ] Sandbox satın alma işlemi mağaza arayüzünde başarıyla tamamlanıyor. - [ ] Bekleyen/başarısız/iptal edilen durumlar uygulamanızda düzgün biçimde işleniyor. - [ ] **İşlemler Adapty'ye bildiriliyor**. - [ ] Observer modu [uygulama kodunuzda etkinleştirilmiş](implement-observer-mode). - [ ] Satın alma işlemi Adapty Event Feed'de görünüyor. - [ ] Yenilemeler, iptaller ve iadeler zamanla yansıtılıyor (geçerli olduğu durumlarda). - [ ] **Paywall görüntülemeleri izleniyor**. Bir paywall gösterildiğinde [`logShowFlow` (iOS SDK v4+) / `logShowPaywall` metodu](present-remote-config-paywalls#track-paywall-view-events) çağrılıyor. - [ ] **Satın almaları geri yükleme, uygulamanız için çalışıyor**. Uygulamayı yeniden yüklemek veya cihaz değiştirmek erişimi doğru şekilde geri yükliyor. - [ ] **Mağaza inceleme gereksinimleri**: - [ ] **Satın almaları geri yükle** eylemi erişilebilir durumda ve geri yükleme akışını tetikliyor. - [ ] Kullanım Koşulları ve Gizlilik Politikası, paywall veya satın alma ekranından erişilebilir durumda ve bir tarayıcıda açılıyor. </TabItem> </Tabs> Adapty SDK entegrasyonu hakkında sorularınız varsa, sağ alttaki yapay zeka sohbet botunu kullanabilir veya [support@adapty.io](mailto:support@adapty.io) adresinden bize ulaşabilirsiniz. --- # File: submit-app-to-app-store --- --- title: "iOS uygulamanızı App Store'a gönderin" description: "Build'inizi App Store Connect'e yükleyin ve iOS abonelik uygulamanızı Apple incelemesine gönderin." --- Adapty entegrasyonunuzu test edip çalıştırdıktan sonra, build'inizi App Store Connect'e yüklemeye ve uygulamanızı Apple incelemesine göndermeye hazırsınız. :::tip Göndermeden önce, Adapty entegrasyonunuzu, satın alma akışlarınızı ve mağaza inceleme gereksinimlerini doğrulamak için [Yayın kontrolü](release-checklist) listesini tamamladığınızdan emin olun. ::: ## Build'inizi App Store Connect'e yükleyin \{#upload-your-build-to-app-store-connect\} ### Adım 1. Uygulamanızı Xcode'da arşivleyin ve App Store Connect'e yükleyin \{#step-1-archive-your-app-in-xcode-and-upload-it-to-app-store-connect\} 1. Xcode'da, build hedefini **Any iOS Device (arm64)** olarak ayarlayın. <img src="/assets/shared/img/build-target.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 2. Üst menü çubuğundan **Product** > **Archive** seçeneğini seçin. <img src="/assets/shared/img/xcode-archive.webp" style={{ border: '1px solid #727272', width: '500px', display: 'block', margin: '0 auto' }} /> 3. Arşivleme işleminin tamamlanmasını bekleyin. **Organizer** penceresi otomatik olarak açılır. Arşivinizi seçin ve **Distribute App** düğmesine tıklayın. <img src="/assets/shared/img/distribute-app.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 4. Dağıtım yöntemi olarak **App Store Connect**'i seçin. Yüklemeyi tamamlamak için adımları takip edin. :::note Uygulama simgesi veya başlatma ekranı gibi gerekli öğeler eksikse yükleme başarısız olabilir. Ayrıntılar için Xcode hata günlüğünü kontrol edin. ::: <img src="/assets/shared/img/distribution-method.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ### Adım 2. Build'i App Store Connect'te kontrol edin \{#step-2-check-the-build-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com)'e gidin ve uygulamanızı açın. 2. **Build** bölümüne gidin. Az önce yüklediğiniz build'in orada göründüğünden emin olun. :::note Yüklemeden sonra build'in App Store Connect'te görünmesi birkaç dakika sürebilir. ::: <img src="/assets/shared/img/app-store-build.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ## Uygulamanızı ve ürünlerinizi incelemeye gönderin \{#submit-your-app-and-products-for-review\} Build **Build** bölümünde göründükten sonra, uygulama içi aboneliklerinizi ekleyin ve uygulamayı Apple incelemesine gönderin. ### Adım 1. Ürünleri gönderime ekleyin \{#step-1-attach-products-to-the-submission\} Her aboneliğin, onu ekleyebilmek için App Store Connect'te **Ready to Submit** durumunda olması gerekir. Bir abonelik hâlâ taslak durumdaysa veya meta verisi eksikse listede görünmez. 1. Aynı sayfada **In-App Purchases and Subscriptions** bölümüne gidin. 2. **Select in-app purchases or subscriptions** seçeneğine tıklayın. <img src="/assets/shared/img/app-store-select-products.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 3. Bu gönderime dahil etmek istediğiniz tüm ürünleri seçin ve **Done**'a tıklayın. ### Adım 2. İnceleme için gönderin \{#step-2-submit-for-review\} 1. Sayfadaki tüm zorunlu alanları doldurun (açıklama, ekran görüntüleri, anahtar kelimeler vb.). 2. **App Store Version Release** bölümünde, onaylandıktan sonra uygulamanızı otomatik, manuel veya belirli bir tarihte yayınlamak isteyip istemediğinizi seçin. 3. **Add for Review**'a, ardından **Submit to App Review**'a tıklayın. Apple uygulamaları genellikle 1–2 gün içinde inceler, ancak inceleme süreleri değişkenlik gösterebilir. ## Uygulamanızı canlı ortamda doğrulayın \{#verify-your-app-in-production\} Apple uygulamanızı onayladıktan sonra: 1. Gerçek bir satın alma yapın (ya da ilk kullanıcının satın almasını bekleyin). 2. Adapty Kontrol Paneli'nde [**Event Feed**](https://app.adapty.io/event-feed)'i açın ve üretim ortamı işlem olaylarının göründüğünü doğrulayın. 3. Abonelik olaylarının (yenilemeler, iptaller) doğru aktığını kontrol edin — bunlar [App Store sunucu bildirimlerinin](enable-app-store-server-notifications) yapılandırılmış olmasına bağlıdır. Üretim ortamı olayları görünmüyorsa, [App Store bağlantı yapılandırmanızı](app-store-connection-configuration) doğrulayın. ## Sonraki adımlar \{#next-steps\} Uygulamanız yayında. Abonelik gelirinizi artırmaya başlayın: - **[A/B testi](ab-tests)**: En iyi dönüşümü sağlayan paywall'ı bulmak için farklı seçenekler deneyin. - **[Analitik](charts)**: MRR, churn ve dönüşüm gibi abonelik metriklerini takip edin. - **Entegrasyonlar**: Abonelik olaylarını [analitik](analytics-integration) ve [attribution](attribution-integration) platformlarına gönderin. --- # File: general --- --- title: "Uygulama ayarları" description: "Adapty'deki genel ayarları ve yapılandırmaları keşfedin." --- Uygulamanızın davranışını, görünümünü ve gelir paylaşımını yönetmek için App Settings sayfasının General sekmesine gidebilirsiniz. Burada uygulamanızın adını ve simgesini özelleştirebilir, Adapty SDK ve API anahtarlarınızı yönetebilir, Small Business Program durumunuzu belirleyebilir ve uygulamanızın analitik ve grafikleri için saat dilimini seçebilirsiniz. ## 1. Uygulama ayrıntıları \{#1-app-details\} <img src="/assets/shared/img/8fa2929-CleanShot_2023-04-21_at_15.16.222x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty arayüzünde uygulamanızı temsil edecek benzersiz bir ad ve simge seçin. Uygulama adı ve simgesinin App Store veya Google Play'deki ad ve simgeyi etkilemeyeceğini unutmayın. Ayrıca uygulamanızın amacını ve içeriğini doğru yansıtan bir App Category seçtiğinizden emin olun. Bu, kullanıcıların uygulamanızı bulmasına ve uygun uygulama mağazası kategorilerinde görünmesine yardımcı olur. ## 2\. Small Business Program Üyeliği ve İndirimli Hizmet Ücreti \{#2-member-of-small-business-program-and-reduced-service-fee\} <img src="/assets/shared/img/825e2be-CleanShot_2023-04-19_at_13.43.292x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Organizasyonunuz Apple'ın [Small Business Program](app-store-small-business-program) programına veya Google'ın [Reduced Service Fee programına](google-reduced-service-fee) kayıtlıysa uygulamalarınız indirimli mağaza komisyonuna tabi olur. Uygulamanız indirimli komisyon programına kayıtlıysa bunu Adapty'e bildirin. Doğru hesaplamalar için bu programların durumunu "Reduced Store Fee" bölümünde belirtin. İndirimli ücret ayarı yalnızca gelecekteki işlemler için geçerlidir. Yürürlüğe girmeden **önce** durumunuzu güncelleyin; Adapty komisyon oranını buna göre ayarlayacaktır. :::warning * İndirimli ücret programındaki katılımınızı uzatıyorsanız **ek bir uygunluk dönemi ekleyin**. * Program üyeliğinizi kaybediyorsanız mevcut uygunluk döneminin **bitiş tarihini değiştirin**. ::: Bu konuyu derinlemesine ele alan makaleler: * [App Store Small Business Program](app-store-small-business-program) * [Google Reduced Service Fee](google-reduced-service-fee) ## 3\. Raporlama saat dilimi \{#3-reporting-timezone\} <img src="/assets/shared/img/47227f9-CleanShot_2023-04-19_at_13.45.302x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bulunduğunuz konuma veya uygulamanızın analitik ve grafiklerinin en alakalı olduğu yere karşılık gelen saat dilimini seçin. Tutarlılık sağlamak için App Store Connect veya Google Play Console hesabınızla aynı saat dilimini kullanmanızı öneririz. Bu saat dilimi ayarının, UTC saat dilimini kullanan Adapty sistemindeki üçüncü taraf entegrasyonları etkilemediğini unutmayın. Saat dilimi ayarlarına, App Settings sayfasının General sekmesindeki Reported timezone bölümünden ulaşabilirsiniz. İlgili kutuyu işaretleyerek Adapty hesabınızdaki tüm uygulamalar için aynı saat dilimini de ayarlayabilirsiniz. ## 4\. Analitik için yükleme tanımı \{#4-installs-definition-for-analytics\} Analitikte yeni bir yükleme olayı olarak neyin tanımlanacağını seçin: | Temel | Açıklama | |------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Yeni device_id'ler | <p>(Önerilen) Uygulamanın mağazadan bir cihaza her yüklenmesi yeni bir yükleme olarak sayılır. Bu hem ilk yüklemeleri hem de yeniden yüklemeleri kapsar.</p><p>Yüklemeler cihaz kimliği başına sayılır ve kullanıcı kimlik doğrulamasından etkilenmez. Profil oluşturma (SDK etkinleştirmede veya çıkış yapıldığında), oturum açma veya uygulama güncelleme ek yükleme olayı oluşturmaz.</p><p>Örneğin, aynı uygulama 5 farklı cihaza yüklendiyse analitikte 5 yükleme görürsünüz.</p> | | Yeni customer_user_id'ler | <p>Bu seçenek, Adapty'de <InlineTooltip tooltip="identify users in Adapty">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Unity](unity-identifying-users), [Kotlin Multiplatform](kmp-quickstart-identify), [Capacitor](capacitor-quickstart-identify)</InlineTooltip> kullanıcıları tanımlayan uygulamalar içindir. </p><p>Oturum açmış kullanıcılar için yalnızca bir customer user ID ile ilişkilendirilen ilk yükleme yükleme olarak sayılır. Ek cihazlardaki yüklemeler yeni yükleme olarak sayılmaz. </p><p>Anonim kullanıcılar (oturum açmamış kullanıcılar) analitikte sayılmaz. </p><p>Uygulamayı yeniden yüklemek veya tekrar oturum açmak ek yükleme oluşturmaz.</p> <p>Uygulama mağazaları ve attribution platformları (App Store Connect, Google Play Console ve AppsFlyer gibi) yüklemeleri cihaz bazlı olarak sayar. Adapty'de yüklemeleri customer user ID'ye göre sayarsanız bu harici hizmetlerden farklı sayılar elde edebilirsiniz.</p><p>⚠️ Adapty'de kullanıcıları tanımlamıyorsanız bu seçenek etkinleştirildiğinde hiçbir yükleme sayılmaz.</p> | | Adapty'deki yeni profiller | (Eski) Her uygulama yüklemesi, yeniden yükleme ve çıkış sırasında oluşturulan anonim profiller yeni yükleme olarak sayılır. | Bu seçeneğin yalnızca [**Analytics**](https://app.adapty.io/analytics) sayfasını etkilediğini ve görünümü ayrıca yapılandırabileceğiniz [**Overview**](https://app.adapty.io/overview) sayfasını etkilemediğini unutmayın. ## 5. App Store fiyat artışı mantığı \{#5-app-store-price-increase-logic\} Adapty analizleri ile App Store Connect sonuçları arasındaki tutarsızlıkları önlemek ve doğru verileri korumak için, App Store Connect'te fiyat artışlarıyla ilgili yapılandırmaları ayarlarken uygun seçeneği belirlemek önemlidir. Adapty'de abonelik fiyat artışlarına uygulanacak mantığı şu şekilde seçebilirsiniz: <img src="/assets/shared/img/b766c8b-CleanShot_2023-07-18_at_19.28.18_22x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Mevcut kullanıcılar için abonelik fiyatı korunur:** Bu seçeneği işaretlediğinizde, App Store Connect'te fiyat değişikliği yapılsa bile mevcut aboneleriniz için geçerli fiyat korunur. Yani mevcut aboneler orijinal abonelik fiyatından ücretlendirilmeye devam eder. - **App Store Connect'te abonelik fiyatı değiştiğinde mevcut aboneler için de değişir:** Bu seçeneği seçerseniz App Store Connect'te yapılan fiyat değişiklikleri mevcut abonelere de uygulanır. Yani mevcut aboneler, App Store Connect'teki güncellenen fiyatlandırmayı yansıtan yeni fiyattan ücretlendirilir. :::warning Seçilen seçeneğin yalnızca Adapty'deki analitiği değil, entegrasyonları ve genel işlem yönetimi davranışını da etkilediğini göz önünde bulundurun. ::: Mevcut aboneler için abonelik fiyatlarını yönetme yaklaşımınızla örtüşen seçeneği belirlediğinizden emin olun. Bu, Adapty analitiği ile App Store Connect'ten elde edilen sonuçlar arasında doğru veri ve senkronizasyonun korunmasına yardımcı olur. ## 6. Kullanıcı hesapları arasında ücretli erişim paylaşımı \{#6-sharing-paid-access-between-user-accounts\} :::link Ana makale: [Kullanıcı hesapları arasında ücretli erişim paylaşımı](sharing-paid-access-between-user-accounts) ::: **Sharing paid access between user accounts** ayarı, birden fazla [kullanıcı profili](identifying-users) aynı satın almaya erişmeye çalıştığında Adapty'nin ne yapacağını belirler. [Sandbox ortamı](test-purchases-in-sandbox) için ayrı bir erişim paylaşımı ayarı belirtebilirsiniz. **Etkin (varsayılan)** Kimliği belirlenmiş kullanıcılar ([Müşteri Kullanıcı Kimliği](identifying-users#set-customer-user-id-on-configuration) atanmış olanlar), cihazları aynı Apple/Google ID ile oturum açmışsa Adapty tarafından sağlanan aynı [access level](access-level)'ı paylaşabilir. Bu, kullanıcının uygulamayı yeniden yükleyip farklı bir e-posta ile giriş yapması durumunda bile önceki satın alımına erişimini korumasını sağlar. Bu seçenekte birden fazla kimliği belirlenmiş kullanıcı aynı access level'ı paylaşabilir. Access level paylaşılıyor olsa da tüm geçmiş ve gelecekteki işlemler; deneme süreleri, abonelik satın alımları, yenilemeler ve daha fazlası dahil olmak üzere tutarlı bir analitik ve eksiksiz bir işlem geçmişi sağlamak amacıyla orijinal Müşteri Kullanıcı Kimliği'nde olay olarak kaydedilir ve aynı profile bağlı kalır. **Erişimi yeni kullanıcıya aktar** Kimliği belirlenmiş kullanıcılar, farklı bir [Müşteri Kullanıcı Kimliği](identifying-users#set-customer-user-id-on-configuration) ile giriş yapsalar veya uygulamayı yeniden yükleseler bile, cihazları aynı Apple/Google ID ile oturum açık olduğu sürece Adapty tarafından sağlanan [access level](access-level)'a erişmeye devam edebilir. Önceki seçenekten farklı olarak Adapty, satın alımı kimliği belirlenmiş kullanıcılar arasında aktarır. Bu sayede satın alınan içeriğe erişim sağlanır; ancak aynı anda yalnızca bir kullanıcı erişime sahip olabilir. Örneğin, KullanıcıA bir abonelik satın alır ve KullanıcıB aynı cihazda oturum açarak işlemleri geri yüklerse KullanıcıB aboneliğe erişim kazanırken KullanıcıA'nın erişimi iptal edilir. Kullanıcılardan biri (yeni veya eski) kimliği belirlenmemişse, access level yine de Adapty'deki bu profiller arasında paylaşılmaya devam eder. Access level aktarılıyor olsa da tüm geçmiş ve gelecekteki işlemler; deneme süreleri, abonelik satın alımları, yenilemeler ve daha fazlası dahil olmak üzere tutarlı bir analitik ve eksiksiz bir işlem geçmişi sağlamak amacıyla orijinal Müşteri Kullanıcı Kimliği'nde olay olarak kaydedilir ve aynı profile bağlı kalır. **Erişimi yeni kullanıcıya aktar** seçeneğine geçtikten sonra, access level'lar profiller arasında hemen aktarılmaz. Belirli bir access level için aktarım süreci; abonelik yenilemesi, geri yükleme veya işlem doğrulama gibi mağazadan bir olay alındığında tetiklenir. **Devre Dışı** Bir access level alan ilk kimliği belirlenmiş kullanıcı profili, bu erişimi kalıcı olarak elinde tutar. İş mantığınızın satın alımların tek bir Müşteri Kullanıcı Kimliği'ne bağlı olmasını gerektirdiği durumlarda en uygun seçenektir. Anonim kullanıcılar arasında access level paylaşımının devam ettiğini unutmayın. Bir satın alımı "ayırmak" için [kullanıcının profilini silebilirsiniz](https://adapty.io/docs/tr/api-adapty/operations/deleteProfile). Silme işleminin ardından access level, ister anonim ister kimliği belirlenmiş olsun, ilk talep eden kullanıcı profiline açık hale gelir. Paylaşımı devre dışı bırakmak yalnızca yeni kullanıcıları etkiler. Kullanıcılar arasında zaten paylaşılmakta olan abonelikler, bu seçenek devre dışı bırakıldıktan sonra da paylaşılmaya devam eder. :::warning Apple ve Google, uygulama içi satın alımların kullanıcılar arasında paylaşılmasını veya aktarılmasını zorunlu kılar; çünkü satın alımı belirli bir kullanıcıyla ilişkilendirmek için Apple/Google ID'ye güvenirler. Paylaşım olmadan, sonraki yeniden yüklemelerde satın alımların geri yüklenmesi çalışmayabilir. Paylaşımı devre dışı bırakmak, kullanıcıların giriş yaptıktan sonra erişimi yeniden kazanamamasına neden olabilir. Paylaşımı yalnızca kullanıcılarınızın satın alma yapmadan önce **giriş yapmasının zorunlu olduğu** durumlarda devre dışı bırakmanızı öneririz. Aksi takdirde, kimliği belirlenmiş bir kullanıcı abonelik satın alıp başka bir hesaba giriş yaparak erişimini kalıcı olarak kaybedebilir. ::: ### Hangi ayarı seçmeliyim? \{#which-setting-should-i-choose\} | Uygulamam... | Seçilecek seçenek | | ------------------------------------------------------------ | ------------------------------------------------------------ | | Giriş sistemi yok ve yalnızca Adapty'nin anonim profil ID'lerini kullanıyor. | Access level'lar her üç seçenekte de anonim profil ID'leri arasında her zaman paylaşıldığından varsayılan seçeneği kullanın. | | İsteğe bağlı giriş sistemine sahip ve müşterilerin hesap oluşturmadan önce satın alım yapmasına izin veriyor. | Hesapsız satın alım yapan müşterilerin işlemlerini daha sonra geri yükleyebilmesini sağlamak için **Erişimi yeni kullanıcıya aktar** seçeneğini belirleyin. | | Satın alım öncesinde hesap oluşturmayı zorunlu kılıyor ancak satın alımların birden fazla Müşteri Kullanıcı Kimliği'ne bağlanmasına izin veriyor. | Aynı anda yalnızca bir Müşteri Kullanıcı Kimliği'nin erişime sahip olmasını sağlarken kullanıcıların ücretli erişimlerini kaybetmeden farklı bir Müşteri Kullanıcı Kimliği ile giriş yapabilmesine olanak tanımak için **Erişimi yeni kullanıcıya aktar** seçeneğini belirleyin. | | Satın alım öncesinde hesap oluşturmayı zorunlu kılıyor ve satın alımları tek bir Müşteri Kullanıcı Kimliği'ne bağlayan katı kurallara sahip. | İşlemlerin hesaplar arasında hiçbir zaman aktarılmamasını sağlamak için **Devre Dışı** seçeneğini belirleyin. | ## 7. SDK ve API anahtarları \{#7-sdk-and-api-keys\} Adapty SDK'larını uygulamanıza entegre etmek için Public SDK anahtarını, Adapty'nin Server API'sine erişmek için ise Secret Key'i kullanın. Gerektiğinde yeni anahtarlar oluşturabilir veya mevcut olanları iptal edebilirsiniz. Developer CLI için token oluşturmak üzere **Settings → Developer API** bölümüne gidin. Bkz. [Authentication](developer-cli-authentication). ## 8. Test cihazları \{#8-test-devices\} Test için kullanılacak cihazları belirterek paywall veya placement değişikliklerinde önbellek gecikmelerini atlayıp anında güncellemeler almalarını sağlayın. Daha fazla bilgi için bkz. [Testing devices](test-devices). ## 9. Placement'lar arası varyant sürekliliği \{#9-cross-placement-variation-stickiness\} Bir test tamamlandıktan sonra kullanıcının testteki varyantlarla ne kadar süre daha sunulmaya devam edeceğini tanımlayın. Bu, analitik doğruluğunu ve kullanıcı deneyimini etkiler; zira kullanıcıya daha önce gördüğünden farklı bir teklif sunmak satın alma kararını etkileyebilir. Maksimum ve varsayılan süreklililik süresi 90 gündür. :::warning Şunları göz önünde bulundurun: - Bu ayarı değiştirmek, daha önce bir varyasyon almış tüm kullanıcıları etkiler. Bu kullanıcılar bir placement gördüklerinde anında yeni bir paywalle uygun hale gelir; bu da çalışan A/B testlerinizin sonuçlarını bozabilir. - Bir kullanıcı için süreklililik süresi dolduysa, o kullanıcıya yeni bir paywall veya A/B testi sunulabilir. Ancak bu durumda bile söz konusu kullanıcı bir daha hiçbir placement'lar arası testin parçası olamaz. ::: ## 10. Uygulamayı Sil \{#delete-the-app\} Artık ihtiyacınız kalmayan bir uygulamayı Adapty'den silebilirsiniz. :::warning Bu işlemin geri alınamaz olduğunu ve uygulamayı ya da verilerini geri yükleyemeyeceğinizi lütfen unutmayın. ::: --- # File: ios-settings --- --- title: "Apple App Store kimlik bilgileri" description: "Sorunsuz abonelik yönetimi için Adapty'de iOS ayarlarını yapılandırın." --- App Store kimlik bilgilerini yapılandırmak ve Adapty iOS SDK'nın sorunsuz çalışmasını sağlamak için Adapty Kontrol Paneli'ndeki App Settings sayfasında yer alan [iOS SDK](https://app.adapty.io/settings/ios-sdk) sekmesine gidin. Ardından aşağıdaki parametreleri yapılandırın: <img src="/assets/shared/img/3d4087e-CleanShot_2023-06-26_at_13.27.042x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> | Alan | Açıklama | |----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Bundle ID** | [Uygulama bundle ID'niz](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id). | | **In-app purchase API (StoreKit 2)** | Uygulama içi satın alma işlem geçmişi isteklerinin güvenli kimlik doğrulaması ve doğrulamasını etkinleştirmek için [anahtarlar](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id). | | **App Store Server Notifications** | Kullanıcıların abonelik durumu değişikliklerini izlemek ve yanıtlamak amacıyla App Store'dan [sunucudan sunucuya bildirimler](enable-app-store-server-notifications) almayı etkinleştirmek için kullanılan URL. | | **App Store Promotional Offers** | Adapty'de belirli ürünler için [Promosyon teklifleri](generate-in-app-purchase-key) oluşturmaya yönelik abonelik anahtarları. | | **Apple app ID** | App Store'daki uygulama ID'niz. Bulmak için App Store Connect'te uygulama sayfanızı açın, sol menüden **App Information** sayfasına gidin ve **Apple ID**'yi kopyalayın. | | **App Store Connect shared secret (LEGACY)** | <p>**Adapty SDK v2.9.0 öncesi için eski anahtar**</p><p></p><p>Uygulamanızda makbuz doğrulaması ve sahteciliği önlemek için kullanılan [bir anahtar](app-store-connection-configuration#step-5-enter-app-store-shared-secret).</p> | --- # File: google-play-store-connection-configuration --- --- title: "Google Play Store entegrasyonunu yapılandırma" description: "Sorunsuz uygulama içi satın alma işlemleri için Adapty'de Google Play Store bağlantısını yapılandırın." --- Bu bölüm, Google Play üzerinden satılan mobil uygulamanızı Adapty ile entegre etme sürecini açıklamaktadır. Play Store'daki uygulama yapılandırma verilerinizi Adapty Kontrol Paneli'ne girmeniz gerekecek. Bu adım, satın almaları doğrulamak ve Adapty içinde Play Store'dan abonelik güncellemeleri almak için kritik öneme sahiptir. Bu işlemi ilk onboarding sırasında tamamlayabilir ya da daha sonra Adapty Kontrol Paneli'nin **App Settings** bölümünden değişiklik yapabilirsiniz. :::danger Yapılandırma değişikliği, yalnızca Adapty paywall'larını entegre ettiğiniz mobil uygulamanızı yayınlamadan önce kabul edilebilir. Yayın sonrasında yapılan değişiklik entegrasyonu bozar ve paywall'lar mobil uygulamanızda gösterilmeyi durdurur. ::: ## Adım 1. Paket adını girin \{#step-1-provide-package-name\} Paket adı, uygulamanızın Google Play Store'daki benzersiz tanımlayıcısıdır. Bu, abonelik işleme gibi Adapty'nin temel işlevleri için gereklidir. 1. [Google Play Developer Console](https://play.google.com/console/u/0/developers)'u açın. 2. ID'sine ihtiyaç duyduğunuz uygulamayı seçin. **Dashboard** penceresi açılır. <img src="/assets/shared/img/7889edb-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Uygulama adının altındaki ürün ID'sini bulun ve kopyalayın. 4. Adapty üst menüsünden [**App settings**](https://app.adapty.io/settings/android-sdk)'i açın. <img src="/assets/shared/img/b00066c-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **App settings** penceresinin **Android SDK** sekmesine, kopyaladığınız **Package name** değerini yapıştırın. ## Adım 2. Hesap anahtarı dosyasını yükleyin \{#step-2-upload-the-account-key-file\} 1. [Servis hesabı anahtar dosyası oluşturma](create-service-account) adımında oluşturduğunuz JSON formatındaki servis hesabı özel anahtar dosyasını **Service account key file** alanına yükleyin. <img src="/assets/shared/img/20fdba1-service_key_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Değişiklikleri onaylamak için **Save** düğmesine tıklamayı unutmayın. **Sıradaki adım** - [Google Play Console'da Gerçek zamanlı geliştirici bildirimlerini (RTDN) etkinleştirme](enable-real-time-developer-notifications-rtdn) --- # File: enable-real-time-developer-notifications-rtdn --- --- title: "Google Play Console'da Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) Etkinleştirme" description: "Adapty için Google Play Console'da Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) etkinleştirerek kritik olaylar hakkında bilgi sahibi olun ve veri doğruluğunu koruyun. İade ve diğer önemli olaylar için Play Store'dan anında güncelleme almak üzere RTDN'yi nasıl kuracağınızı öğrenin" --- Gerçek zamanlı geliştirici bildirimlerini (RTDN) kurmak, veri doğruluğu açısından kritik öneme sahiptir; bu sayede Play Store'dan iade bilgileri ve diğer olaylar dahil güncellemeleri anında alabilirsiniz. ## Bildirimleri Etkinleştirme \{#enable-notifications\} 1. **Google Cloud Pub/Sub**'ın etkin olduğundan emin olun. [Bu bağlantıyı](https://console.cloud.google.com/flows/enableapi?apiid=pubsub) açın ve uygulama projenizi seçin. **Google Cloud Pub/Sub**'ı henüz etkinleştirmediyseniz burada etkinleştirmeniz gerekir. <img src="/assets/shared/img/pubsub.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Adapty üst menüsünden [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) sayfasına gidin ve **Google Play RTDN topic name** başlığının yanındaki **Enable Pub/Sub API** alanının içeriğini kopyalayın. <img src="/assets/shared/img/a72ff2d-copy_topic.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note **Enable Pub/Sub API** alanının içeriği yanlış bir formattaysa (doğru format `projects/...` ile başlar), yardım için [Enable Pub/Sub API alanındaki yanlış formatı düzeltme](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) bölümüne bakın. ::: 3. [Google Play Console](https://play.google.com/console/)'u açın, uygulamanızı seçin ve **Monetize with Play** -> **Monetization setup** bölümüne gidin. **Google Play Billing** bölümünde **Enable real-time notifications** onay kutusunu işaretleyin. 4. Adapty **App Settings**'de kopyaladığınız **Enable Pub/Sub API** alanının içeriğini **Topic name** alanına yapıştırın. 5. Google Play Console'da **Save changes**'e tıklayın. <img src="/assets/shared/img/e55ba0e-paste_topic_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Bildirimleri Test Etme \{#test-notifications\} Gerçek zamanlı geliştirici bildirimlerine başarıyla abone olup olmadığınızı kontrol etmek için: 1. Google Play Console ayarlarındaki değişiklikleri kaydedin. 2. Google Play Console'daki **Topic name** alanının altında **Send test notification**'a tıklayın. <img src="/assets/shared/img/rtdn-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adapty'de [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) sayfasına gidin. Test bildirimi gönderildiyse, konu adının üzerinde durumunu göreceksiniz. <img src="/assets/shared/img/rtdn-adapty-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Enable Pub/Sub API Alanındaki Yanlış Formatı Düzeltme \{#fixing-incorrect-format-in-enable-pubsub-api-field\} **Enable Pub/Sub API** alanının içeriği yanlış bir formattaysa (doğru format `projects/...` ile başlar), sorunu gidermek için şu adımları izleyin: ### 1. API Etkinleştirme ve İzinleri Doğrulama \{#1-verify-api-enablement-and-permissions\} Gerekli tüm API'lerin etkinleştirildiğinden ve izinlerin servis hesabına doğru şekilde verildiğinden emin olun. Bu adımları daha önce tamamlamış olsanız bile, hiçbir alt adımın atlanmadığından emin olmak için tekrar gözden geçirmeniz önemlidir. Aşağıdaki bölümlerdeki adımları tekrarlayın: 1. [Google Play Console'da Geliştirici API'lerini Etkinleştirme](enabling-of-devepoler-api) 2. [Google Cloud Console'da Servis Hesabı Oluşturma](create-service-account) 3. [Google Play Console'da Servis Hesabına İzin Verme](grant-permissions-to-service-account) 4. [Google Play Console'da Servis Hesabı Anahtar Dosyası Oluşturma](create-service-account-key-file) 5. [Google Play Store Entegrasyonunu Yapılandırma](google-play-store-connection-configuration) ### 2. Alan Politikalarını Düzenleme \{#2-adjust-domain-policies\} **Domain restricted contacts** ve **Domain restricted sharing** politikalarını değiştirin: 1. [Google Cloud Console](https://console.cloud.google.com/)'u açın ve uygulamanızı yönetmek için servis hesabını oluşturduğunuz projeyi seçin. 2. **Quick Access** bölümünde **IAM & Admin**'i seçin. <img src="/assets/shared/img/google-cloud-IAM-and-Admin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Sol panelde **Organization Policies**'i seçin. 4. **Domain restricted contacts** politikasını bulun. <img src="/assets/shared/img/google-cloud-policy-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Actions** sütunundaki üç nokta düğmesine tıklayın ve **Edit policy**'yi seçin. 6. Politika düzenleme penceresinde: 1. **Policy source** altında **Override parent's policy** radyo düğmesini seçin. 2. **Policy enforcement** altında **Replace** radyo düğmesini seçin. 3. **Rules** altında **ADD A RULE** düğmesine tıklayın. <img src="/assets/shared/img/google-cloud-edit-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **New rule** -> **Policy values** altında **Allow All**'u seçin. <img src="/assets/shared/img/google-cloud-allow-all-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **SET POLICY**'ye tıklayın. 7. **Domain restricted sharing** politikası için 4-6. adımları tekrarlayın. Son olarak, **Google Play RTDN topic name** başlığının yanındaki **Enable Pub/Sub API** alanının içeriğini yeniden oluşturun. Alan artık doğru formatta olacaktır. Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN) başarıyla etkinleştirdikten sonra güncellenen politikalar için **Policy source**'u **Inherit parent's policy** olarak geri aldığınızdan emin olun. ## Ham Olay Yönlendirme \{#raw-events-forwarding\} Bazen Google'dan ham S2S olaylarını almaya devam etmek isteyebilirsiniz. Adapty kullanırken bunları almaya devam etmek için endpoint'inizi **URL for forwarding raw Google events** alanına eklemeniz yeterlidir; ham olayları Google'dan geldiği gibi ileteceğiz. <img src="/assets/shared/img/e388892-001774-September-22-GhkjOFbT.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- **Sırada ne var** Adapty SDK'yı şu platformlar için kurun: - [Android](sdk-installation-android) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: apple-search-ads --- --- title: "Apple Ads" description: "Abonelik dönüşümlerini optimize etmek için Apple Ads'i Adapty ile entegre edin." --- :::important **App settings** içindeki Apple Ads entegrasyonu yalnızca temel analitik ve SplitMetrics Acquire ile Asapty entegrasyonları için kullanılır. [Adapty Ads Manager](adapty-ads-manager), ayrı bir bağlantı kullanır. Apple Ads hesabınızı [Adapty Ads Manager](adapty-ads-manager-get-started) üzerinden bağlayın. ::: Adapty, Apple Ads'ten attribution verisi almanıza ve kampanya ile anahtar kelime segmentasyonuyla metriklerinizi analiz etmenize yardımcı olur. Adapty, Apple Ads için attribution verilerini SDK ve AdServices Framework aracılığıyla otomatik olarak toplar. Apple Ads entegrasyonunu kurduktan sonra Adapty, Apple Ads'ten attribution verisi almaya başlar. Bu verilere profiller sayfasından kolayca erişip görüntüleyebilirsiniz. <img src="/assets/shared/img/ba4a3e9-CleanShot_2023-08-21_at_15.14.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Entegrasyonu Kurma \{#set-up-integration\} ### Adapty'yi AdServices framework'üne bağlama \{#connect-adapty-to-the-adservices-framework\} Apple Ads, [AdServices](https://developer.apple.com/documentation/adservices) aracılığıyla Adapty Kontrol Paneli'nde bazı yapılandırmalar gerektirir ve bunu uygulama tarafında da etkinleştirmeniz gerekir. AdServices framework'ü aracılığıyla Adapty üzerinden Apple Ads'i kurmak için şu adımları izleyin: #### 1. Adım: Genel anahtarı edinin \{#step-1-obtain-public-key\} Adapty Kontrol Paneli'nde [Settings -> Apple Ads](https://app.adapty.io/settings/apple-search-ads) sayfasına gidin. Önceden oluşturulmuş genel anahtarı (Adapty sizin için bir anahtar çifti sağlar) bulun ve kopyalayın. <img src="/assets/shared/img/baa5998-CleanShot_2023-08-21_at_14.55.542x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Apple Ads attribution için alternatif bir hizmet veya kendi çözümünüzü kullanıyorsanız, kendi özel anahtarınızı yükleyebilirsiniz. ::: #### Adım 2: Apple Ads'de kullanıcı yönetimini yapılandırın \{#step-2-configure-user-management-on-apple-ads\} [Apple Ads hesabınızda](https://ads.apple.com/app-store) **Settings > User Management** sayfasına gidin. Adapty'nin attribution verilerini çekebilmesi için başka bir Apple ID hesabını davet etmeniz ve bu hesaba API Account Manager erişimi vermeniz gerekir. Erişiminiz olan herhangi bir hesabı kullanabilir ya da bu amaç için yeni bir hesap oluşturabilirsiniz. Önemli olan nokta şudur: bu Apple ID ile Apple Ads'e giriş yapabilmeniz gerekir. <img src="/assets/shared/img/ec183b2-kdjsfldsfjkdsfdfd.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### Adım 3: API kimlik bilgileri oluşturun \{#step-3-generate-api-credentials\} Bir sonraki adım olarak, Apple Ads'e yeni eklenen hesapla giriş yapın. Apple Ads arayüzünde Settings -> API bölümüne gidin. Daha önce kopyaladığınız genel anahtarı ilgili alana yapıştırın. Yeni API kimlik bilgileri oluşturun. #### Adım 4: Adapty'yi Apple Ads kimlik bilgileriyle yapılandırın \{#step-4-configure-adapty-with-apple-ads-credentials\} Apple Ads ayarlarından Client ID, Team ID ve Key ID alanlarını kopyalayın. Adapty Kontrol Paneli'nde bu kimlik bilgilerini ilgili alanlara yapıştırın. <img src="/assets/shared/img/7356113-CleanShot_2023-08-21_at_15.08.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Uygulamanızı AdServices ağına bağlama \{#connect-your-app-to-the-adservices-network\} [AdServices framework kurulumunu](#connect-the-adservices-framework) tamamladıktan sonra Adapty, Apple Search Ad attribution verilerini otomatik olarak toplamaya başlar. Herhangi bir SDK kodu eklemenize gerek yoktur. iOS uygulamaları için bu attribution verisi **her zaman** diğer kaynaklardan gelen verilere göre öncelikli olacaktır. Bu davranış istenmiyor ise aşağıdaki talimatları kullanarak ASA attribution'ı *devre dışı bırakın*. ## Entegrasyonu devre dışı bırakma \{#disable-integration\} Apple Search Ads attribution'ını kapatmak için [**App Settings** -> **Apple Search Ads** sekmesini](https://app.adapty.io/settings/apple-search-ads) açın ve **Receive Apple Search Ads attribution** anahtarını kapatın. <img src="/assets/shared/img/asa-disable.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning Bunu devre dışı bırakmanın ASA analizlerinin tamamen durmasına yol açacağını unutmayın. Sonuç olarak, ASA artık analizlerde kullanılmayacak ve entegrasyonlara gönderilmeyecektir. Ayrıca SplitMetrics Acquire ve Asapty, doğru çalışmak için ASA attribution'a bağlı olduklarından işlevlerini yitirecektir. Bu değişiklikten önce alınan attribution verileri etkilenmeyecektir. ::: ## Kendi Anahtarlarınızı Yükleme \{#uploading-your-own-keys\} :::note İsteğe bağlı Bu adımlar Apple Ads attribution için zorunlu değildir; yalnızca Asapty gibi diğer hizmetlerle veya kendi çözümünüzle çalışmak için gereklidir. ::: ASA attribution için başka hizmetler ya da kendi çözümünüzü kullanıyorsanız kendi genel-özel anahtar çiftinizi kullanabilirsiniz. ### Adım 1 \{#step-1\} Terminal'de özel anahtar oluşturun ```text showLineNumbers title="Text" openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem ``` Adapty Settings -> Apple Ads bölümünden yükleyin (Upload private key butonu) ### Adım 2 \{#step-2\} Terminal'de genel anahtar oluşturun ```text showLineNumbers title="Text" openssl ec -in private-key.pem -pubout -out public-key.pem ``` Bu genel anahtarı, API Account Manager rolüne sahip hesabın Apple Ads ayarlarında kullanabilirsiniz. Böylece oluşturulan Client ID, Team ID ve Key ID değerlerini hem Adapty hem de diğer hizmetler için kullanabilirsiniz. --- # File: account --- --- title: "Hesap detayları ve Faturalandırma" description: "Adapty hesabınızı yönetin ve daha iyi abonelik takibi için ayarları optimize edin." --- **Account** sayfası; profilinizi, ekip üyelerinizi ve faturalandırmayı yönetmenizi sağlar. Sayfada üç sekme bulunur: - [Genel](#general-settings) - [Abonelik ve Faturalandırma](#billing-info) - [Üyeler](#members) Hesap ayarlarınıza erişmek için sağ üst köşedeki **Account** seçeneğine tıklayın ya da [app.adapty.io/account](https://app.adapty.io/account) adresine gidin. <img src="/assets/shared/img/account-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Genel ayarlar \{#general-settings\} General sekmesi; profilinizi, hesap ayarlarınızı, görüntüleme tercihlerinizi ve rapor yapılandırmanızı içerir. - **Profile**: Adınızı, soyadınızı ve şirket adınızı girin. Şirket adı en fazla 256 karakter olabilir. - **Account settings**: Kayıtlı e-posta adresinizi görüntüleyin ve şifrenizi değiştirin. - **Date & Time formats**: Tarih ve saatlerin Adapty genelinde nasıl görüntüleneceğini seçin: - **American format**: January 31, 2022 ve 12 saatlik format (AM/PM) - **European format**: 31 January, 2022 ve 24 saatlik format (16:00) - **Email reports**: Uygulamalarınızın biri veya tamamı için günlük, haftalık ya da aylık raporlar ayarlayın. Tüm uygulamalar için özet rapor alın ya da seçtiğiniz her uygulama için ayrıntılı rapor edinin. <img src="/assets/shared/img/account-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Abonelik & Faturalama \{#billing-info\} **Subscription & Billing** sekmesi; ödeme bilgilerinizi ve özellik erişiminizi yönetmenizi sağlar: - Ödeme bilgilerini ekleyin veya güncelleyin - Faturalama bilgilerini inceleyin - Ek ücretli özellikler satın alın [Özellikler ve fiyatlandırma](https://adapty.io/pricing) hakkında daha fazla bilgi edinin. ## Üyeler \{#members\} Ekip üyelerinizi hesap ayarlarınızdan yönetebilirsiniz. Ekip üyesi eklemek için e-posta adresleriyle davet gönderin ve bir rol atayın. Ekip üyelerini ve erişim haklarını yönetme hakkında daha fazla bilgi için [buraya](members-settings) bakın. --- # File: members-settings --- --- title: "Üyeler" description: "Adapty'nin kontrol panelinde üye ayarlarını ve izinlerini yönetin." --- :::note Bu sayfa, Adapty kontrol paneli üyeleri hakkındadır. Uygulamanızın kullanıcılarına farklı access level'lar vermek istiyorsanız [Access Level](access-level) sayfasına göz atın. ::: Adapty kontrol paneli üyelik sistemi, ekip üyelerine farklı düzeylerde erişim izni vermenizi ve her üye için uygulamaları belirlemenizi sağlar. ## Roller \{#roles\} Adapty kontrol panelinde üyeler için aşağıdaki roller mevcuttur: | Rol | Faturalandırmaya Erişim | Yeni üye ekleme | Her şeyi değiştirme | Tüm bölümlere erişim | |-------------|------------------------|-----------------|---------------------|----------------------| | Owner | ✅ | ✅ | ✅ | ✅ | | Admin | ❌ | ✅ | ✅ | ✅ | | Developer | ❌ | ❌ | ✅ | ❌ | | Viewer | ❌ | ❌ | ❌ | ✅ | | Support | ❌ | ❌ | ❌ | ❌ | | ASA manager | ❌ | ❌ | ❌ | ❌ | - **Owner:** Owner, Adapty hesabının özgün oluşturucusudur ve en yüksek düzeyde erişime ve kontrole sahiptir. Owner'lar Adapty faturalamasına tam erişime sahip olup ödeme bilgilerini ve abonelik planlarını yönetebilir. Bunun yanı sıra, yalnızca Owner'lar ve Admin'ler yeni üyeler için uygulama erişimini belirleyebilir. Her Adapty hesabı için yalnızca bir Owner olabilir. - **Admin:** Admin rolüne sahip üyeler, seçilen uygulamalara tam erişime sahiptir. Paywall oluşturma ve değiştirme, A/B testi yapma, analitik inceleme ve söz konusu uygulamalardaki üyeleri yönetme gibi çeşitli yönetim görevlerini gerçekleştirebilirler. - **Developer:** Developer rolüne sahip üyeler, analitik ve hesap üyeleri dışında tüm varlıklara tam erişime sahiptir. Herhangi bir faturalama ayarına erişemezler. Bu rol; paywall, A/B testi ve diğer yapıları kuran, Adapty'yi uygulamanıza entegre eden ancak finansal verilere erişmemesi gereken kişiler için tasarlanmıştır. - **Viewer:** Viewer rolüne sahip üyeler, seçilen uygulamalara yalnızca okuma erişimine sahiptir. Bilgileri görüntüleyebilirler ancak paywall ve A/B testi oluşturup değiştiremez, diğer özellikleri düzenleyemez, yeni kullanıcı davet edemez, yeni uygulama oluşturamaz ve uygulama ayarlarını değiştiremezler. - **Support:** Support rolüne sahip üyeler, seçilen uygulamalarda yalnızca kullanıcı profillerine erişebilir. Yeni üye ekleme veya Adapty'nin diğer bölümlerine erişme gibi işlemler gerçekleştiremezler. Bu rol, özellikle abonelikle ilgili soruları olan veya sorun giderme desteğine ihtiyaç duyan müşterilere yardımcı olması gereken destek ekipleri ya da bireyler için uygundur. - **ASA manager:** ASA manager rolüne sahip üyeler yalnızca [Adapty Ads Manager](adapty-ads-manager) kontrol paneline erişebilir. ## Üye ekle \{#add-a-member\} Adapty'de 256 takım üyesine kadar davet gönderebilirsiniz. Yeni üye eklemek ücretsizdir. :::note Yalnızca Adapty'de henüz kayıtlı olmayan e-posta adreslerini davet edebilirsiniz. Eğer iş arkadaşınızın bağımsız bir hesabı varsa, farklı bir e-posta adresi deneyin ya da mevcut hesabını silmesi için Adapty desteğiyle iletişime geçin. ::: Takıma yeni üye eklemek için: 1. Sağ üstteki **Account** seçeneğine tıklayın ve **Members** sekmesini açın. 2. **Invite member** seçeneğine tıklayın. <img src="/assets/shared/img/invite-member.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Üyenin e-posta adresini girin. 4. Listeden bir [rol](#roles) seçin. 5. Erişim vermek istediğiniz uygulamaları seçin. 6. (İsteğe bağlı) Gelecekte eklenecek uygulamalara otomatik olarak erişim vermek için **Always allow access to new apps** seçeneğini etkinleştirin. 7. **Save** seçeneğine tıklayın. <img src="/assets/shared/img/add-member.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Hesap sahipliğini devretme \{#transfer-account-ownership\} **Hesap sahipliğini** tümüyle devretmeniz gerekiyorsa destek ekibimizle [support@adapty.io](mailto:support@adapty.io) adresinden iletişime geçin. **Uygulama sahipliğini** devretmeniz gerekiyorsa daha fazla bilgi için [ilgili kılavuzu](transfer-apps) inceleyin. --- # File: set-up-app-store-connect --- --- title: "App Store Connect'i Kurma" description: "İlk kez uygulama geliştirenlere yönelik, Apple Developer Program'a kaydolma ve uygulama içi satın almalar için App Store Connect kurulumu rehberi." --- **İlk iOS uygulamanızı geliştiriyorsanız**, Adapty'yi entegre etmeden önce Apple Developer hesabınızı ve App Store Connect'i kurmanız gerekir. :::note Zaten bir Apple Developer hesabınız ve App Store Connect'te kayıtlı bir uygulamanız varsa bu rehberi atlayıp doğrudan [App Store ile ilk entegrasyon](initial_ios) sayfasına geçebilirsiniz. ::: ## Adım 1. Apple Developer Program'a Kaydolun \{#step-1-enroll-in-apple-developer-program\} App Store'da uygulama dağıtmak ve uygulama içi satın alma satmak için [Apple Developer Program](https://developer.apple.com/programs/)'a katılmanız gerekir. ### Kayıt türünü seçin \{#choose-enrollment-type\} Apple iki farklı kayıt türü sunar: | | Bireysel | Organizasyon | |-----------------------------------|-----------------------|-----------------------------------| | **Kimler için** | Bireysel geliştiriciler | Şirketler, ekipler, kar amacı gütmeyenler | | **D-U-N-S Numarası gerekli mi** | Hayır | Evet | | **Uygulamalar yayımlanır** | Kendi adınıza | Organizasyonunuzun adına | | **Ekip yönetimi** | Mevcut değil | Mevcut | :::tip Bir organizasyon olarak kaydoluyorsanız **D-U-N-S Numarası**'na ihtiyacınız vardır. Bu, Dun & Bradstreet tarafından verilen benzersiz dokuz haneli bir iş tanımlayıcısıdır. [Organizasyonunuzun zaten bir numaraya sahip olup olmadığını kontrol edebilir](https://developer.apple.com/enroll/duns-lookup/) ya da yeni bir tane talep edebilirsiniz — bağlantı, arama sayfasının altında yer alır. D-U-N-S Numarası almanız 5 iş gününe kadar sürebilir. ::: ### Kaydolun \{#enroll\} 1. [Apple Developer Program kayıt sayfasına](https://developer.apple.com/programs/enroll/) gidin. 2. Apple ID'nizle giriş yapın. Hesabınız yoksa önce oluşturun. 3. Kayıt türünüze (bireysel veya organizasyon) göre adımları takip edin. 4. Yıllık ücreti ödeyin. Apple kaydınızı işleme aldıktan sonra [App Store Connect](https://appstoreconnect.apple.com)'e erişim sağlarsınız. Kayıt işlemi genellikle 48 saate kadar sürer. Organizasyonlar için D-U-N-S doğrulaması gerekiyorsa daha uzun sürebilir. ## Adım 2. App Store Connect'te uygulamanızı kurun \{#step-2-set-up-your-app-in-app-store-connect\} Uygulama içi satın alma satabilmek için App Store Connect'te ilk kurulumu tamamlamanız gerekir. Bu; sözleşmeleri imzalamayı, ödeme bilgilerini eklemeyi ve uygulamanızı kaydetmeyi kapsar. ### Paid Applications Sözleşmesini İmzalayın \{#sign-the-paid-applications-agreement\} App Store'da satış yapabilmek için Apple, Paid Applications Sözleşmesi'ni imzalamanızı zorunlu kılar. Bu durum hem ücretli uygulamalar hem de ücretsiz uygulamalardaki uygulama içi satın almalar için geçerlidir. 1. [App Store Connect](https://appstoreconnect.apple.com/business)'teki **Business** sayfasına gidin. 2. **Paid Apps** sözleşmesini bulun ve **Review and Agree**'ye tıklayın. 3. Gerekli bilgileri tamamlayın: - **Bankacılık bilgileri**: Apple'ın kazançlarınızı göndereceği bir banka hesabı ekleyin. - **Vergi bilgileri**: Satış yapmak istediğiniz ülkeler için vergi formlarını doldurun. - **İletişim bilgileri**: İletişim bilgilerinizi girin. :::important Sözleşmenin aktif hale gelebilmesi için üç bölümün de (bankacılık, vergi, iletişim) tamamlanması zorunludur. Sözleşme aktif olana kadar uygulama içi satın alma satamazsınız. ::: ### Bundle ID Oluşturun \{#create-a-bundle-id\} Bundle ID, uygulamanızı Apple ekosisteminde benzersiz şekilde tanımlar. Uygulamanızı App Store Connect'e kaydetmek ve Adapty entegrasyonunu yapılandırmak için buna ihtiyaç duyarsınız. 1. [Apple Developer portalını](https://developer.apple.com/account) açın. 2. **Certificates, Identifiers & Profiles** → **Identifiers** bölümüne gidin. 3. Yeni bir tanımlayıcı kaydetmek için **+**'ya tıklayın. 4. **App IDs**'i seçin ve **Continue**'ye tıklayın. 5. Tür olarak **App**'i seçin ve **Continue**'ye tıklayın. 6. Alanları doldurun: - **Description**: Bu Bundle ID'yi tanımanıza yardımcı olacak bir ad (örneğin, "My Subscription App"). - **Bundle ID**: **Explicit**'i seçin ve ters domain formatında benzersiz bir tanımlayıcı girin (örneğin, `com.yourcompany.yourapp`). 7. **Capabilities** bölümünde aşağı kaydırın ve **In-App Purchase**'ı işaretleyin. 8. **Continue**'ye, ardından **Register**'a tıklayın. ### Uygulamanızı App Store Connect'e kaydedin \{#register-your-app-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'teki **Apps** sayfasına gidin. 2. **+** → **New App**'e tıklayın. 3. Gerekli alanları doldurun: - **Platforms**: **iOS**'u seçin. - **Name**: App Store'da görünecek uygulama adınız. - **Primary language**: Uygulama meta verilerinizin varsayılan dili. - **Bundle ID**: Önceki adımda oluşturduğunuz Bundle ID'yi seçin. - **SKU**: Uygulamanız için benzersiz bir tanımlayıcı (kullanıcılara görünmez). Örneğin, `my_subscription_app_2025`. 4. **Create**'e tıklayın. Uygulamanız artık App Store Connect'e kayıtlıdır ve Adapty entegrasyonuna hazırdır. ## Sırada ne var \{#whats-next\} - [App Store ile ilk entegrasyon](initial_ios): App Store uygulamanızı Adapty'ye bağlayın - [SDK entegrasyonu](quickstart-sdk): Adapty SDK'yı uygulama kodunuza entegre edin - [Sandbox testi](test-purchases-in-sandbox): Uygulama içi satın almalarınızı yayınlamadan önce test edin - [iOS uygulamanızı App Store'a gönderin](submit-app-to-app-store): Derlemenizi yükleyin ve Apple incelemesi için gönderin - [App Store Küçük İşletme Programı](app-store-small-business-program): App Store komisyonunuzu %30'dan %15'e düşürün --- # File: app-store-products --- --- title: "App Store'da Ürün" description: "Adapty'nin abonelik araçlarını kullanarak App Store ürünlerini verimli şekilde yönetin." --- Bu sayfa, App Store Connect'te ürün oluşturma konusunda rehberlik sağlar. Bu bilgiler doğrudan Adapty'nin işlevselliğiyle ilgili olmasa da, App Store Connect hesabınızda ürün oluştururken karşılaştığınız sorunlarda işinize yarayabilir. Adapty'ye bağlanacak bir ürün oluşturmak için: 1. **App Store Connect**'i açın. Sol taraftaki menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne gidin. <img src="/assets/shared/img/148c3b5-subscriptions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Henüz bir abonelik grubu oluşturmadıysanız, **Subscription Groups** başlığının altındaki **Create** düğmesine tıklayarak işlemi başlatın. App Store Connect'teki [Subscription Groups](https://developer.apple.com/help/app-store-connect/manage-subscriptions/offer-auto-renewable-subscriptions), ürünlerinizi kategorilere ayırır ve yönetir; kullanıcıların farklı teklifler arasında sorunsuz geçiş yapmasını sağlar. Bir aboneliği grup dışında oluşturmanın mümkün olmadığını unutmayın. 3. Açılan **Create Subscription Group** penceresinde, **Reference Name** alanına yeni bir abonelik grubu adı girin. Referans adı, uygulamanızdaki farklı abonelik gruplarını ayırt etmenize ve yönetmenize yardımcı olan, sizin belirlediğiniz bir etiket veya tanımlayıcıdır. Referans adı kullanıcılara görünmez; yalnızca dahili kullanım ve organizasyon amacıyla tasarlanmıştır. App Store Connect arayüzünde abonelik gruplarını yönetirken belirli gruplara kolayca başvurmanızı sağlar. Özellikle birden fazla abonelik teklifiniz varsa ya da bunları uygulamanızın yapısına uygun bir şekilde kategorize etmek istiyorsanız bu özellik oldukça kullanışlıdır. <img src="/assets/shared/img/3f93c44-create_subscription_group.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Abonelik grubunun oluşturulmasını onaylamak için **Create** düğmesine tıklayın. 5. Abonelik grubu oluşturulur ve açılır. Artık grup içinde abonelikler oluşturabilirsiniz. **Subscriptions** başlığının altındaki **Create** düğmesine tıklayın. Mevcut bir gruba yeni abonelik ekleyecekseniz, **Subscriptions** başlığının yanındaki **Plus** düğmesine tıklayın. <img src="/assets/shared/img/22fc643-add_subscription.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Açılan **Create Subscription** penceresinde, **Reference Name** alanına abonelik adını ve **Product ID** alanına aboneliğe ait benzersiz kodu girin. Referans adı, App Store Connect içindeki uygulama içi aboneliğiniz için özel bir tanımlayıcı işlevi görür. App Store'da kullanıcılara görünmez. Oluşturmak istediğiniz aboneliği doğru şekilde tanımlayan, anlaşılır ve okunabilir bir açıklama kullanmanızı öneririz. Bu adın 64 karakteri geçmemesi gerektiğini unutmayın. Product ID, geliştirme aşamasında ürününüze erişmek ve uygulama içi abonelikleri yönetmek üzere tasarlanmış bir servis olan Adapty ile senkronize etmek için gerekli olan benzersiz bir alfanümerik tanımlayıcıdır. Product ID'de yalnızca alfanümerik karakterlere, noktalara ve alt çizgilere izin verilir. <img src="/assets/shared/img/04aca55-create_subscription.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Aboneliğin oluşturulmasını onaylamak için **Create** düğmesine tıklayın. 8. Abonelik oluşturulur ve açılır. Şimdi **Subscription Duration** listesinden aboneliğin süresini seçin. Abonelik süresi abonelik adında belirtilmiş olsa bile **Subscription Duration** alanını doldurmayı unutmayın. <img src="/assets/shared/img/f56cf0f-subscription_duration.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. Sıra abonelik fiyatını belirlemeye geldi. Bunun için Subscription Prices başlığının altındaki **Add Subscription Price** düğmesine tıklayın. Bu düğmeyi bulmak için sayfayı aşağı kaydırmanız gerekebilir. 10. Açılan **Subscription Price** penceresinde, **Country or Region** listesinden temel ülkeyi ve **Price** listesinden temel para birimini seçin. Apple daha sonra bu temel fiyata ve güncel döviz kurlarına dayanarak tüm 175 ülke veya bölge için fiyatları otomatik olarak hesaplayacaktır. <img src="/assets/shared/img/de1cec8-subscription_price.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 11. **Next** düğmesine tıklayın. Açılan **Price by Country or Region** penceresinde tüm ülkeler için otomatik olarak yeniden hesaplanmış fiyatları göreceksiniz. İsterseniz bunları değiştirebilirsiniz. <img src="/assets/shared/img/2a047a6-price_by_country.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 12. Bölgesel fiyatları güncelledikten sonra pencerenin altındaki **Next** düğmesine tıklayarak devam edin. 13. Açılan **Confirm Subscription Price?** penceresinde nihai fiyatları dikkatlice inceleyin. Fiyatları düzeltmek için **Back** düğmesine tıklayarak **Price by Country or Region** penceresine geri dönebilir ve güncelleyebilirsiniz. Fiyatlardan memnunsanız **Confirm** düğmesine tıklayın. <img src="/assets/shared/img/d2b2031-confirm_prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 14. **Confirm Subscription Price?** penceresini kapattıktan sonra abonelik penceresindeki **Save** düğmesine tıklamayı unutmayın. Bu adımı atlarsanız abonelik oluşturulmaz ve girdiğiniz tüm veriler kaybolur. Şimdiye kadar anlatılan adımların Otomatik Yenilenebilir Abonelik yapılandırmasına odaklandığını belirtmek gerekir. Ancak diğer türde uygulama içi satın alma işlemleri kurmak istiyorsanız, kenar çubuğunda "Subscriptions" yerine **In-App Purchases** sekmesine tıklayabilirsiniz. Bu, çeşitli uygulama içi satın alma türlerini yönetip oluşturabileceğiniz bölüme yönlendirecektir. <img src="/assets/shared/img/5663d85-in-app_purchases.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Ürünleri Adapty'ye Ekleyin \{#add-products-to-adapty\} Uygulama içi satın alımlarınızı, aboneliklerinizi ve tekliflerinizi App Store Connect'e eklemeyi tamamladıktan sonra, bir sonraki adım [bu ürünleri Adapty'ye eklemektir](create-product). --- # File: apple-app-privacy --- --- title: "Apple Uygulama Gizliliği" description: "Apple uygulama gizlilik politikalarını ve bunların abonelik uygulamanıza etkisini anlayın." --- Apple, hem App Store Connect'teki **App Privacy** bölümünde hem de uygulama manifest dosyası olarak tüm yeni uygulamalar ve uygulama güncellemeleri için gizlilik bildirimi zorunlu kılmaktadır. Adapty, uygulamanızın üçüncü taraf bir bağımlılığı olduğundan, Adapty'yi kullanıcı verileriyle nasıl kullandığınızı bildirmeniz gerekir. ## Apple uygulama gizlilik manifest'i \{#apple-app-privacy-manifest\} `PrivacyInfo.xcprivacy` adlı [gizlilik manifest dosyası](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests), uygulamanızın hangi özel verileri kullandığını ve neden kullandığını açıklar. Her uygulama sahibi olarak uygulamanız için bir manifest dosyası oluşturmanız gerekir. Ayrıca ek SDK'lar entegre ediyorsanız, [gizlilik manifest'i ve imza gerektiren SDK'lar](https://developer.apple.com/support/third-party-SDK-requirements/) listesinde yer alanların manifest dosyalarının dahil edildiğinden emin olun. Uygulamanızı derlediğinizde Xcode tüm bu manifest dosyalarını alıp tek bir dosyada birleştirir. Adapty, [gizlilik manifest'i ve imza gerektiren SDK'lar](https://developer.apple.com/support/third-party-SDK-requirements/) listesinde yer almasa da kolaylık sağlaması açısından Adapty SDK'nın 2.10.2 ve üzeri sürümleri bu dosyayı içermektedir. Manifest'i edinmek için SDK'yı güncellediğinizden emin olun. Adapty, uygulama gizlilik raporu olarak da bilinen manifest dosyasına herhangi bir veri eklenmesini zorunlu kılmasa da takip amacıyla Adapty'nin `customerUserId` özelliğini kullanıyorsanız bunu manifest dosyanızda şu şekilde belirtmeniz gerekmektedir: 1. Gizlilik bilgileri dosyanızdaki `NSPrivacyCollectedDataTypes` dizisine bir sözlük ekleyin. 2. Sözlüğe `NSPrivacyCollectedDataType`, `NSPrivacyCollectedDataTypeLinked` ve `NSPrivacyCollectedDataTypeTracking` anahtarlarını ekleyin. 3. `NSPrivacyCollectedDataTypes` sözlüğünüzdeki `NSPrivacyCollectedDataType` anahtarı için `NSPrivacyCollectedDataTypeUserID` dizesini ekleyin ([Manifest dosyasında bildirilecek veri kategorileri ve türleri listesi](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Describe-the-data-your-app-or-third-party-SDK-collects)ndeki `UserID` veri türünün tanımlayıcısıdır). 4. `NSPrivacyCollectedDataTypes` sözlüğünüzdeki `NSPrivacyCollectedDataTypeTracking` ve `NSPrivacyCollectedDataTypeLinked` anahtarları için `true` değerini ekleyin. 5. `NSPrivacyCollectedDataTypes` sözlüğünüzdeki `NSPrivacyCollectedDataTypePurposes` anahtarının değeri olarak `NSPrivacyCollectedDataTypePurposeProductPersonalization` dizesini kullanın. Paywall'larınızı özel niteliklere sahip kitlelere hedefliyorsanız, kullandığınız özel nitelikleri ve bunların [manifest dosyasında bildirilecek veri kategorileri ve türleriyle](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests) eşleşip eşleşmediğini dikkatlice değerlendirin. Eşleşiyorsa her veri türü için yukarıdaki adımları tekrarlayın. Topladığınız tüm veri türlerini ve kategorilerini bildirdikten sonra, [Apple dokümantasyonunda](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Create-your-apps-privacy-report) açıklandığı şekilde uygulamanızın gizlilik raporunu oluşturun. ## App Store Connect'te Apple uygulama gizlilik bildirimi \{#apple-app-privacy-disclosure-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com/)'te uygulamanızı açın ve **App Privacy** bölümüne gidin. **Get Started** düğmesine tıklayın. <img src="/assets/shared/img/app-privacy-get-started.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Yes, we collect data from this app** seçeneğini seçin ve **Next** düğmesine tıklayın. <img src="/assets/shared/img/app-privacy-data-collection.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Veri türleri \{#data-types\} Aşağıdaki tablo, Apple'ın bildirmenizi zorunlu kıldığı veri türlerini ve Adapty'nin hangilerine ihtiyaç duyduğunu göstermektedir. **Bu yalnızca Adapty'yi kapsamaktadır.** Uygulamanız başka SDK'lar veya kendi kodunuz aracılığıyla ek veri topluyorsa bu veri türlerini de seçin. ✅ = Adapty tarafından zorunlu 👀 = Gerekli olabilir (ayrıntılar için aşağıya bakın) ❌ = Adapty tarafından zorunlu değil — uygulamanız bu veriyi başka yollarla topluyorsa seçin | Veri türü | Zorunlu | Not | |---------------------------------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Tanımlayıcılar | ✅ | <p>Kullanıcıları customerUserId ile tanımlıyorsanız 'User ID' seçeneğini seçin.</p><p></p><p>Adapty IDFA topladığından 'Device ID' seçeneğini seçmeniz gerekir.</p> | | Satın Almalar | ✅ | Adapty, kullanıcılardan satın alma geçmişi toplar. | | Ad, telefon numarası veya e-posta adresi gibi İletişim Bilgileri | 👀 | **`updateProfile`** yöntemiyle ad, telefon numarası veya e-posta adresi gibi kişisel veriler iletiyorsanız zorunludur. | | Kullanım Verileri | 👀 | Amplitude, Mixpanel, AppMetrica veya Firebase gibi analiz SDK'ları kullanıyorsanız gerekebilir. | | Konum | ❌ | Adapty hassas konum verisi toplamaz. Uygulamanız topluyorsa seçin. | | Sağlık & Fitness | ❌ | Adapty sağlık veya fitness verisi toplamaz. Uygulamanız topluyorsa seçin. | | Hassas Bilgi | ❌ | Adapty hassas bilgi toplamaz. Uygulamanız topluyorsa seçin. | | Kullanıcı İçeriği | ❌ | Adapty kullanıcı içeriği toplamaz. Uygulamanız topluyorsa seçin. | | Tanılama | ❌ | Adapty tanılama verisi toplamaz. Uygulamanız topluyorsa seçin. | | Tarama Geçmişi | ❌ | Adapty tarama geçmişi toplamaz. Uygulamanız topluyorsa seçin. | | Arama Geçmişi | ❌ | Adapty arama geçmişi toplamaz. Uygulamanız topluyorsa seçin. | | Kişiler | ❌ | Adapty kişi listesi toplamaz. Uygulamanız topluyorsa seçin. | | Finansal Bilgi | ❌ | Adapty finansal bilgi toplamaz. Uygulamanız topluyorsa seçin. | ### Zorunlu veri türleri \{#required-data-types\} #### Satın Almalar \{#purchases\} Adapty kullanırken uygulamanızın **Satın Alma Geçmişi** topladığını bildirmeniz zorunludur. <img src="/assets/shared/img/feb3b9f-CleanShot_2023-08-25_at_12.32.552x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### Tanımlayıcılar \{#identifiers\} Adapty kullanırken aşağıdaki tanımlayıcıları bildirmeniz zorunludur: - **Device ID** — Adapty IDFA toplar. - **User ID** — kullanıcıları **`customerUserId`** ile tanımlıyorsanız zorunludur. <img src="/assets/shared/img/93f3daa-CleanShot_2023-08-25_at_12.35.272x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Veri kullanımı \{#data-usage\} **Veri türlerini** kaydettikten sonra verilerin nasıl kullanıldığını belirtmeniz gerekir: 1. **Purchases** bloğunun içindeki **Set up purchase history** seçeneğine tıklayın. <img src="/assets/shared/img/purchase-privacy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Apple, satın alma geçmişi verilerinin nasıl kullanıldığını sorduğunda Adapty için aşağıdakileri seçin: - **Analytics** — Adapty, satın alma geçmişini gelir analitiği, kohortlar ve metrikler için kullanır. - **Product Personalization** — Adapty, satın alma verilerini kitle segmentasyonu ve paywall hedefleme için kullanır. - **App Functionality** — Adapty, satın almaları doğrular, access level'ları yönetir ve abonelik durumunu takip eder. Uygulamanız satın alma verilerini başka amaçlarla kullanıyorsa (örneğin Adapty entegrasyonları aracılığıyla satın alma olaylarını reklam platformlarına gönderiyorsanız) ek amaçları da seçin. <img src="/assets/shared/img/purchase-history.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Next** düğmesine tıklayın. 4. **Device ID** ve **User ID** (kullanılıyorsa) için: 1. **User/Device ID** bloğunun içindeki **Set up user/device ID** seçeneğine tıklayın. 2. Apple, tanımlayıcı verilerinin nasıl kullanıldığını sorduğunda Adapty için aşağıdakileri seçin: - **App Functionality** — Adapty, kullanıcı profillerini yönetmek, satın almaları ilişkilendirmek ve access level'ları takip etmek için tanımlayıcıları kullanır. Adapty entegrasyonları aracılığıyla attribution verilerini üçüncü taraf platformlara (AppsFlyer veya Adjust gibi) gönderiyorsanız **Third-Party Advertising** seçeneğini de seçin. Uygulamanız tanımlayıcıları başka amaçlarla kullanıyorsa ek amaçları da seçin. <img src="/assets/shared/img/user-id-privacy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Next** düğmesine tıklayın. --- # File: apple-family-sharing --- --- title: "Apple Aile Paylaşımı" description: "Paylaşılan abonelikleri desteklemek için Adapty'de Apple Aile Paylaşımı'nı etkinleştirin." --- Apple'ın aile paylaşımı özelliği, uygulama içi satın alımların aile üyeleri arasında paylaşılmasını sağlar. Video akış hizmetleri ve çocuk uygulamaları gibi grup odaklı uygulamaların kullanıcılarına, Apple ID'lerini paylaşmak zorunda kalmadan abonelikleri bölüşmenin kolay bir yolunu sunar. Beş adede kadar aile üyesinin bir aboneliği kullanabilmesine olanak tanıyan [Aile Paylaşımı](https://developer.apple.com/documentation/storekit/supporting-family-sharing-in-your-app), uygulamanızda müşteri etkileşimini ve elde tutma oranını artırabilir. Bu kılavuzda, abonelikleri Aile Paylaşımı'na nasıl dahil edeceğinizi ve Adapty'nin aile içinde paylaşılan satın almaları nasıl yönettiğini açıklayacağız. Belirli bir ürün için Aile Paylaşımı'nı etkinleştirmeye başlamak için [App Store Connect](https://appstoreconnect.apple.com/)'e gidin. Aile Paylaşımı, hem yeni hem de mevcut uygulama içi satın almalar için varsayılan olarak kapalıdır; bu nedenle her uygulama içi satın alma için ayrı ayrı etkinleştirmeniz gerekir. Bunu kolayca yapmak için **uygulamanızın sayfasına** gidin, ilgili uygulama içi satın alma sayfasına geçin ve Aile Paylaşımı bölümündeki **Turn On** seçeneğini belirleyin. Family Sharing'i bir ürün için etkinleştirdiğinizde, **bir daha kapatılamayacağını** unutmayın; çünkü bu, aboneliğini aile üyeleriyle paylaşmış olan kullanıcıların deneyimini olumsuz etkiler. Ayrıca, yalnızca non-consumable ürünlerin ve aboneliklerin paylaşılabildiğini göz önünde bulundurun. <img src="/assets/shared/img/6db165a-CleanShot_2023-03-28_at_17.15.342x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Görüntülenen modalda kurulum işlemini tamamlamak için **Confirm** düğmesine tıklayın. Bunu yaptıktan sonra, Aile Paylaşımı bölümünün "This subscription can be shared by everyone in a family group." mesajını gösterecek şekilde güncellenmesi gerekir. Bu, aboneliğin artık Aile Paylaşımı için etkinleştirildiğini ve beş adede kadar aile üyesiyle paylaşılabildiğini doğrular. Adapty, Family Sharing desteğini fazladan bir çaba gerektirmeden kolayca sağlar. Tek yapmanız gereken [ürünlerinizi](app-store-products) App Store üzerinden yapılandırmak; App Store Connect'te **Family Sharing**'i **etkinleştirdiğinizde** bu özellik **Adapty**'de otomatik olarak kullanılabilir hale gelir ve webhook üzerinden bir event olarak alınır. :::note Family Sharing'in sandbox ortamında desteklenmediğini lütfen unutmayın. ::: Göz önünde bulundurulabilecek bir nokta şu: kullanıcı bir abonelik satın alıp aile üyeleriyle paylaştığında, aboneliğin onlara ulaşması **bir saate kadar gecikebilir**. Apple bu gecikmeyi, kullanıcının fikrini değiştirip isterse paylaşımı geri alabilmesi için tasarladı. Ancak abonelik yenilendiğinde, aile üyelerine erişimin sağlanmasında herhangi bir gecikme yaşanmaz. Bir kullanıcı Aile Paylaşımlı bir uygulama içi ürün satın aldığında, işlem makbuzunda normalde göründüğü gibi yer alır; ancak buna ek olarak `PURCHASED` değerine sahip `in_app_ownership_type` adında yeni bir alan eklenir. Bunun yanı sıra, tüm aile üyeleri için yeni bir işlem oluşturulur. Bu işlem, orijinal satın alma işlemine kıyasla farklı bir `web_order_line_item_id` ve `original_transaction_id` değerine sahip olur; ayrıca `FAMILY_SHARED` değerine sahip bir `in_app_ownership_type` alanı içerir. Doğru gelir hesabı için Adapty analizlerinde yalnızca `in_app_ownership_type` değeri `PURCHASED` olan işlemler sayılır. `FAMILY_SHARED` işlemleri gelir ve dönüşüm metriklerinden hariç tutulur. **Aile Paylaşımı işlemleri için gönderilen olaylar.** `FAMILY_SHARED` işlemleri yalnızca **Access level updated** olayını tetikler. Ürün bazındaki abonelik olayları aile üyeleri için tetiklenmez. | Olay | `FAMILY_SHARED` | `PURCHASED` | | --- | --- | --- | | **Access level updated** | Evet | Evet | | **Subscription started** | Hayır | Evet | | **Trial started** | Hayır | Evet | | **Subscription renewed** | Hayır | Evet | | **Subscription expired** | Hayır | Evet | | **Subscription refunded** | Hayır | Evet | | **Billing issue detected** | Hayır | Evet | Downstream analitiğiniz **Subscription started** olayına dayanıyorsa, aile üyeleri bu olayda görünmez. Aktif aile üyelerini tespit etmek için **Access level updated** olayını kullanın. Adapty'deki diğer aile üyelerini tespit etmek için event detaylarına bakabilirsiniz. Önce orijinal aile satın alma işlemini bulun. Ardından söz konusu işlemin event detaylarını inceleyerek aynı ürünü, satın alma tarihini ve bitiş tarihini arayın. Event detaylarını analiz ederek orijinal satın alma işlemiyle ilişkili diğer aile üyeliği işlemlerini tespit edebilirsiniz. --- # File: app-store-small-business-program --- --- title: "App Store Küçük İşletme Programı" description: "Apple'ın Küçük İşletme Programı'nı, gelirleriniz üzerindeki etkisini ve Adapty'nin analizlerini anlayın" --- :::link Play Store'daki karşılık gelen program için bkz. [Google İndirimli Hizmet Ücreti](google-reduced-service-fee). ::: 1 milyon ABD Dolarına kadar yıllık App Store geliri elde eden kuruluşlar, Apple'ın [Küçük İşletme programına](https://developer.apple.com/app-store/small-business-program/) katılmaya hak kazanır. Programa kaydolursanız, standart %30 mağaza komisyon oranı **%15'e** indirilir. Program üyeleri, doğru gelir hesaplamaları ve entegrasyon etkinliği işleme süreçlerinin sağlanması için **Adapty ayarlarını değiştirmelidir**. --- title: "App Store Küçük İşletme Programı" description: "Küçük İşletme Programı için Adapty'yi nasıl yapılandıracağınızı ve programa nasıl başvuracağınızı öğrenin." metadataTitle: "App Store Küçük İşletme Programı | Adapty Dokümanları" --- Bu makale şunları açıklar: * [Uygulamanız Küçük İşletme Programı'na kayıtlıysa Adapty'yi nasıl yapılandırırsınız](#configure-adapty) * [Mağaza komisyonunuzu düşürmek istiyorsanız programa nasıl başvurursunuz](#apply-for-the-program) ## Adapty'yi Yapılandırma \{#configure-adapty\} Adapty, indirimli komisyon oranını [analizlerinize](analytics) ve [entegrasyon etkinliklerinize](analytics-integration) uygulayabilir. Bunu etkinleştirmek için Küçük İşletme Programı durumunuzu uygulama bazında belirtin. :::warning SBP durumunuzu Adapty'de **onay aldığınız anda** yapılandırın. Geç yapılan değişiklikler, iletilmiş webhook etkinliklerini yeniden yazamaz ([ayrıntılar](#retroactive-setting-changes)). ::: 1. [**App Settings** → **General**](https://app.adapty.io/account) sayfasını açın. 2. **Small Business Program** bölümünü bulun. 3. **Add period** düğmesine tıklayın. 4. Üyelik başlangıç tarihini seçin. 5. Bitiş tarihi seçin ya da bu durumu süresiz olarak uzatmak için **At the current moment** onay kutusunu etkinleştirin. İleride [uygunluğu kaybederseniz](#losing-eligibility) bitiş tarihini değiştirebilirsiniz. 6. **Apply** düğmesine tıklayın. Kuruluşunuz programa uygun olmaya devam ederse üyelik bir sonraki takvim yılına aktarılır. Ancak üyelik durumu yalnızca **belirttiğiniz tarih aralığına** uygulanır. * Yeni bir üyelik dönemi eklemek için **Add period** düğmesine tıklayın. * Bu durumu süresiz olarak uzatmak için **At the current moment** onay kutusunu etkinleştirin. Yapılandırmanızı doğrulamak için [Gelir grafiğini](revenue) açın ve **Proceeds after store commission** seçeneğini seçin. Görüntülenen gelirin indirimli komisyon oranını yansıttığını onaylayın. ## Programa Başvurun \{#apply-for-the-program\} ### Uygunluk gereksinimleri \{#eligibility-requirements\} Apple, SBP uygunluğunu **yıllık gelirinize** göre belirler; bu, önceki takvim yılının mağaza komisyonu ve vergiler **düşüldükten sonraki** satışlarıdır. Uygun olmak için kuruluşunuzun ve <InlineTooltip tooltip="İlişkili Geliştirici Hesapları">Çoğunluk sahipliğine (>%50) sahip olduğunuz veya karar alma yetkisine sahip olduğunuz hesaplar.</InlineTooltip> yıllık gelirinin toplam 1 milyon USD veya altında olması gerekir. Yeni oluşturulan kuruluşlar programa başvurmaya otomatik olarak hak kazanır. ### Başvurmadan önce \{#before-you-apply\} Aşağıdakileri karşıladığınızdan emin olun: - Apple Geliştirici Programında Hesap Sahibisiniz - App Store Connect'te en son Ücretli Uygulamalar sözleşmesini kabul ettiniz - Tüm İlişkili Geliştirici Hesaplarınızı listeleyebiliyorsunuz ### Kayıt \{#enrollment\} 1. [App Store Küçük İşletme Programı kayıt sayfasına](https://developer.apple.com/app-store/small-business-program/) gidin. 2. **Enroll** düğmesine tıklayın ve Apple Geliştirici hesabınızla oturum açın. 3. Önceden doldurulmuş bilgileri (ad, e-posta, Team ID) inceleyin ve gönderin. ### İnceleme \{#review\} İnceleme süreci bir aydan fazla sürebilir. Uygun bulunursanız Apple'dan bir onay e-postası alırsınız. Onaylandıktan sonra bir bekleme süresi vardır. İndirimli komisyon, Apple'ın [bir sonraki mali döneminin](https://adapty.io/apple-fiscal-calendar/) 15. gününde geçerli olur. Daha önceki işlemlere uygulanmaz. ### Üyelik hakkını kaybetme \{#losing-eligibility\} Mevcut takvim yılı içindeki toplam geliriniz 1 milyon USD'yi aştığında program üyeliğinizi kaybedersiniz ve Apple standart %30 satış komisyonunu uygulamaya başlar. :::important İşletmeniz Küçük İşletme Programından ayrılırsa, ayarlarınızdaki çıkış tarihini **hemen değiştirin**. Aksi takdirde Adapty komisyonu indirimli oranla hesaplamaya devam eder. ::: Yıllık geliriniz 1 milyon USD'nin altına düştükten sonraki **yıl** programa yeniden hak kazanabilirsiniz. Daha fazla ayrıntı için [resmi program koşullarını](https://developer.apple.com/app-store/small-business-program/) okuyun. ## Geriye dönük ayar değişiklikleri \{#retroactive-setting-changes\} Adapty'de indirimli komisyon durumunuzu geriye dönük geçerlilik tarihiyle değiştirdiğinizde, yeni komisyon oranı Adapty'nin verilerinde farklı zamanlamalarda görünür: | Oranın göründüğü yer | Oranı değiştirdikten sonra ne olur | | --- | --- | | Analytics kontrol paneli (Revenue, Proceeds, MRR, ARR) | Adapty, günlük yeniden hesaplama çalıştığında yeni oranı 24 saat içinde uygular. | | S3, GCS ve BigQuery dışa aktarımları | Adapty, yeni oranı bir sonraki zamanlanmış dışa aktarımda uygular. | | Halihazırda iletilmiş webhook olayları | Adapty, webhook olaylarını iletildikten sonra değiştiremez. Bu olaylar eski oranı korur. | Veri ambarınız webhook olaylarından gelen gelir verilerini depoluyorsa, bu kayıtlar eski komisyon oranını korur. Mutabakat sağlamak için etkilenen dönemi analytics kontrol panelinden alın ya da S3, GCS veya BigQuery'ye yeni bir dışa aktarım oluşturun. --- # File: android-products --- --- title: "Play Store'da Ürün" description: "Adapty ile Android ürünlerini yönetin, uygulama içi satın almaları kolaylaştırın ve monetizasyon stratejilerinizi optimize edin." --- Bu sayfa, Play Store'da ürün oluşturma konusunda rehberlik sağlar. Bu bilgiler doğrudan Adapty'nin işlevselliğiyle ilgili olmasa da, Google Play Console'da ürün oluştururken sorunlarla karşılaşırsanız faydalı bir kaynak olarak hizmet eder. Ürün, Play Store'da uygulamanız içinde sunduğunuz ve genellikle satın alınabilir dijital bir öğe veya hizmeti ifade eder. Bunlar; tek seferlik satın almalar, abonelikler veya kullanıcıların uygulamanızı kullanırken edinebileceği diğer dijital ürünler gibi uygulama içi ürünleri kapsayabilir. [Google'ın faturalandırma sisteminde](https://developer.android.com/google/play/billing/compatibility), abonelikler her biri çeşitli indirimler veya teklifler sunan birden fazla temel plan içerebilir. Bu yapı üç ana bileşenden oluşur: - **Abonelikler:** Kullanıcıların belirli bir süre boyunca yararlanabileceği avantaj paketlerini temsil eder (satılan öğeler). Örneğin, abonelere premium özellikler sunan bir "Gold seviyesi". - **Temel planlar:** Faturalandırma dönemlerinin, yenileme türlerinin ve fiyatların belirli yapılandırmalarını temsil eder (öğelerin nasıl satıldığı). Örnekler arasında "otomatik yenileme ile yıllık" veya "ön ödemeli aylık" sayılabilir. - **Teklifler:** Uygun kullanıcılara sunulan ve temel planın fiyatını değiştiren indirimlerdir. Örneğin, "yeni kullanıcılar için 14 günlük ücretsiz deneme". ## Play Store'da ürün nasıl oluşturulur? \{#how-to-create-a-product-in-play-store\} Ürün, uygulamanız içinde sunduğunuz ve genellikle satın alınabilir dijital bir öğe veya hizmeti ifade eder. Bunlar; tek seferlik satın almalar, abonelikler veya kullanıcıların uygulamanızı kullanırken edinebileceği diğer dijital ürünler gibi uygulama içi ürünleri kapsayabilir. Android cihazlar için ürün ayarlamak üzere: 1. Google Play Console'un sol menüsünde [**Monetize** -> **Subscriptions**](https://console.cloud.google.com/iam-admin/serviceaccounts) veya [**Monetize** -> **In-app products**](https://console.cloud.google.com/iam-admin/serviceaccounts) bölümünü açın. <img src="/assets/shared/img/6eff1d1-subscription_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Create subscription** düğmesine tıklayın. <img src="/assets/shared/img/af7fe02-create_subscription_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Açılan **Create subscription** penceresinde, **Product ID** alanına abonelik kimliğini ve **Name** alanına abonelik adını girin. Ürün kimliği benzersiz olmalı, bir rakam veya küçük harfle başlamalı; alt çizgi (\_) ve nokta (.) karakterlerini de içerebilir. Geliştirme sürecinde ürününüze erişmek ve Adapty ile senkronize etmek için kullanılır. Bir Ürün Kimliği Google Play Console'da bir ürüne atandıktan sonra, ürün silinse bile başka uygulamalar için yeniden kullanılamaz. Ürün kimliğinizi adlandırırken standart bir format takip etmeniz önerilir. Daha kısa bir yaklaşım kullanarak ürünü `<abonelik adı>.<access level>` şeklinde adlandırmanızı öneririz. Ardından süre ve faturalandırma sıklığını haftalık, aylık gibi temel planlar aracılığıyla kontrol edebilirsiniz. Ad yalnızca kendi referansınız içindir; Google Play Store listenizde görünecektir, dolayısıyla istediğiniz açıklayıcı bir adı kullanabilirsiniz. 55 karakterle sınırlıdır. 4. Abonelik oluşturma işlemini onaylamak için **Create** düğmesine tıklayın. :::note Adapty'de Google Play abonelik ürünleri Adapty ürünleri, Google Play abonelikleri için Temel Planlarla eşleşir; çünkü bunlar müşterilerin satın alabileceği ürünlerdir. Adapty, mevcut Google Play aboneliklerini ve bunlara karşılık gelen temel planlarını herhangi bir ek işlem gerektirmeksizin sorunsuz biçimde geçirir. Ancak Adapty'ye yeni bir ürün eklediğinizde hem temel plan kimliğini hem de ürün kimliğini girmeniz gerekir. ::: ### Temel plan oluşturma \{#create-a-base-plan\} Abonelik ürünleri için temel plan eklemeniz gerekir. Temel planlar, müşterilerin aboneliğinizi satın alması için faturalandırma dönemini, fiyatı ve yenileme türünü belirler. Müşterilerin doğrudan bir abonelik ürünü satın almadığını unutmayın; her zaman bir abonelik içindeki temel planı satın alırlar. Temel plan oluşturmak için: 1. Google Play Console'un sol menüsünde [**Monetize** -> **Subscriptions**](https://console.cloud.google.com/iam-admin/serviceaccounts) bölümünü açın. Ardından temel plan eklemek istediğiniz aboneliği bulun. 2. Aboneliğin yanındaki **View subscription** düğmesine tıklayın. <img src="/assets/shared/img/4072a2a-subscriptions_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Abonelik detayları açıldıktan sonra **Base plans and offers** başlığının altındaki **Add base plan** düğmesine tıklayın. Bulmak için aşağı kaydırmanız gerekebilir. <img src="/assets/shared/img/b493b60-add_base_plan.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Açılan **Add base plan** penceresinde, **Plan ID** alanına temel plan için benzersiz bir tanımlayıcı girin. Bir rakam veya küçük harfle başlamalı; rakamlar (0-9), küçük harfler (a-z) ve kısa çizgi (-) içerebilir. Gerekli alanları doldurun. <img src="/assets/shared/img/8146763-CleanShot_2023-07-20_at_16.51.412x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Bölgeye göre fiyatları belirtin. <img src="/assets/shared/img/8b26e1d-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Kurulumu tamamlamak için **Save** düğmesine tıklayın. 7. Temel planı etkin hale getirmek için **Activate** düğmesine tıklayın. Adapty'de abonelik ürünlerinin yalnızca tek bir temel planı olabileceğini ve bu planın tutarlı bir süre ile yenileme türüne sahip olması gerektiğini unutmayın. ### Yedek ürünler \{#fallback-products\} :::warning Geriye dönük uyumsuz temel planlar için destek Adapty SDK'larının eski sürümleri, Google Billing Library v5+ özelliklerini (özellikle abonelik başına birden fazla temel plan ve teklifler) desteklemez. Google Play Console'da **[backwards compatible](https://support.google.com/googleplay/android-developer/answer/12124625?hl=en#backwards_compatible)** olarak işaretlenen temel planlara yalnızca bu SDK sürümleriyle erişilebilir. Abonelik başına yalnızca bir temel plan geriye dönük uyumlu olarak işaretlenebilir. ::: <img src="/assets/shared/img/b5e70cb-CleanShot_2023-07-20_at_17.03.252x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty'deki gelişmiş Google abonelik yapılandırmalarından ve özelliklerinden tam olarak yararlanmak için geriye dönük uyumlu bir yedek ürün kurma imkânı sunuyoruz. Bu yedek ürün, yalnızca eski Adapty SDK sürümlerini kullanan uygulamalar için kullanılır. Google Play ürünleri oluştururken artık ürünün Play Console'da geriye dönük uyumlu olarak işaretlenip işaretlenmeyeceğini belirtme seçeneğiniz bulunmaktadır. Adapty bu bilgiyi, ürünün SDK'nın eski sürümleriyle (2.5 ve altı) satın alınıp alınamayacağını belirlemek için kullanır. Örneğin, iki temel plan sunan `subscription.premium` adında bir aboneliğiniz olduğunu varsayalım: haftalık (geriye dönük uyumlu) ve aylık. Adapty'ye `subscription.premium:weekly` ürünü eklerseniz, geriye dönük uyumlu bir ürün belirtmeniz gerekmez. Ancak `subscription.premium:monthly` ürünü söz konusu olduğunda, geriye dönük uyumlu bir ürün belirtmeniz gerekir. Bunu yapmazsanız, Google 4. faturalandırma kütüphanesinde istemeden `subscription.premium:weekly` ürünü satın alınabilir. Bu senaryoyu çözmek için, temel planı da aylık olan ve geriye dönük uyumlu olarak işaretlenmiş ayrı bir ürün oluşturmanız gerekir. Bu sayede `subscription.premium:monthly` seçeneğini belirleyen kullanıcılar, doğru sıklıkta faturalandırılır. ## Adapty'ye ürün ekleme \{#add-products-to-adapty\} App Store Connect'te uygulama içi satın almalarınızı, aboneliklerinizi ve tekliflerinizi eklemeyi tamamladıktan sonra, bir sonraki adım [bu ürünleri Adapty'ye eklemektir](create-product). --- # File: google-play-data-safety --- --- title: "Google Play Veri Güvenliği" description: "Adapty'de Google Play Veri Güvenliği politikalarıyla uyumluluğu sağlayın." --- Google Play'de bulunan Veri Güvenliği bölümü, uygulama geliştiricilerin uygulamaları tarafından toplanan veya paylaşılan veriler ile uygulamalarının kritik gizlilik ve güvenlik önlemleri hakkında kullanıcıları bilgilendirmeleri için basit bir yöntem sunar. Bu bilgiler, kullanıcıların hangi uygulamaları indirip kullanacakları konusunda daha bilinçli kararlar vermesini sağlar. Aşağıda, Adapty'nin topladığı veriler hakkında Google Play'e gerekli bilgileri sağlamanıza yardımcı olacak kısa bir kılavuz bulunmaktadır. ## Veri Toplama ve Güvenlik \{#data-collection-and-security\} <img src="/assets/shared/img/3508c24-image4.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Uygulamanız gerekli kullanıcı verisi türlerinden herhangi birini topluyor veya paylaşıyor mu?** Adapty kullanıcının satın alma geçmişini topladığından 'Evet'i seçin. **Uygulamanız tarafından toplanan tüm kullanıcı verileri aktarım sırasında şifreleniyor mu?** Adapty verileri aktarım sırasında şifrelediğinden 'Evet'i seçin. **Kullanıcılara verilerinin silinmesini talep etmeleri için bir yol sunuyor musunuz?** 'Evet'i seçiyorsanız, müşterilerinizin veri silme talebinde bulunmak için destek ekibinizle iletişime geçebilmesini sağlayın. Müşteriyi doğrudan Adapty kontrol panelinden veya REST API aracılığıyla silebilirsiniz. ## Veri Türleri \{#data-types\} Aşağıda Google'ın raporlama için gerektirdiği veri türlerinin listesi yer almakta olup Adapty'nin her bir veri türünü toplayıp toplamadığını belirttik. | Veri Türü | Detaylar | | :--------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Konum | Adapty tarafından toplanmaz | | Sağlık ve Fitness | Adapty tarafından toplanmaz | | Fotoğraflar ve Videolar | Adapty tarafından toplanmaz | | Dosyalar ve Belgeler | Adapty tarafından toplanmaz | | Takvim | Adapty tarafından toplanmaz | | Kişiler | Adapty tarafından toplanmaz | | Kullanıcı İçeriği | Adapty tarafından toplanmaz | | Tarama Geçmişi | Adapty tarafından toplanmaz | | Arama Geçmişi | Adapty tarafından toplanmaz | | Uygulama Bilgisi ve Performansı | Adapty tarafından toplanmaz | | Web Tarama | Adapty tarafından toplanmaz | | İletişim Bilgileri | Adapty tarafından toplanmaz | | Finansal Bilgiler | Adapty kullanıcıların satın alma geçmişini toplar | | Kişisel Bilgiler ve Tanımlayıcılar | Adapty, Adapty SDK'ya açıkça iletmeniz durumunda Kullanıcı Kimliği ve ad, e-posta adresi, telefon numarası vb. dahil diğer tanımlayıcı iletişim bilgilerini toplar. | | Cihaz ve Diğer Tanımlayıcılar | Adapty cihaz kimliğine ilişkin verileri toplar. | ## Veri Kullanımı ve İşleme \{#data-usage-and-handling\} ### Kullanıcı Kimlikleri \{#user-ids\} **1. Bu veriler toplanıyor mu, paylaşılıyor mu, yoksa her ikisi de mi?** Bu veriler Adapty tarafından toplanmaktadır. Adapty ile hizmet sağlayıcı sayılmayan üçüncü taraflar arasında kurulu entegrasyonlar kullanıyorsanız, buraya "Paylaşıldı" seçeneğini de eklemeniz gerekebilir. **2. Bu veriler geçici olarak mı işleniyor?** 'Hayır'ı seçin. **3. Bu veri toplama uygulamanız için zorunlu mu, yoksa kullanıcılar toplanıp toplanmayacağını seçebilir mi?** Bu veri toplama zorunludur ve kapatılamaz. <img src="/assets/shared/img/2c60161-image5.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **4. Bu kullanıcı verisi neden toplanıyor? / Bu kullanıcı verisi neden paylaşılıyor?** 'App functionality' ve 'Analytics' onay kutularını seçin. <img src="/assets/shared/img/07a3c9e-image2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Finansal Bilgiler \{#financial-info\} Adapty kullanıyorsanız, Google Play Console'daki Veri türleri bölümünde uygulamanızın 'Purchase history' bilgilerini topladığını bildirmeniz zorunludur. <img src="/assets/shared/img/1057870-image7.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Cihaz veya Diğer Kimlikler \{#device-or-other-ids\} <img src="/assets/shared/img/d10f132-CleanShot_2023-03-01_at_17.55.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/ccb1a2a-image5.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Sonraki Adımlar \{#next-steps\} Veri güvenliği seçimlerinizi yaptıktan sonra Google, uygulamanızın gizlilik bölümünün önizlemesini gösterecektir. Daha önce belirtildiği gibi "Financial Info" ve "Device or other IDs" seçeneklerini işaretlediyseniz, gizlilik bilgileriniz aşağıdaki örneğe benzer şekilde görünecektir. <img src="/assets/shared/img/e8d9b73-image3.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Uygulamanızı App Review için göndermeye hazırsanız, uygulamanızı göndermeye hazırlamayla ilgili daha fazla yönlendirme için [Yayın Kontrol Listesi](release-checklist) belgemize başvurun. --- # File: google-reduced-service-fee --- --- title: "Google İndirimli Hizmet Ücreti" description: "Google'ın İndirimli Hizmet Ücreti'ni, gelirinize ve Adapty analizlerine etkisini anlayın" --- :::link App Store'daki karşılığı için bkz. [App Store Küçük İşletme Programı](app-store-small-business-program). ::: Google Play'in [İndirimli Hizmet Ücreti programı](https://support.google.com/googleplay/android-developer/answer/112622?hl=en), yıllık kazancınızın ilk 1 milyon ABD Doları'na uygulanan komisyonu %30'dan **%15**'e düşürür. Aynı takvim yılı içinde 1 milyon ABD Doları'nı aşan kazançlar standart %30 oranında ücretlendirilir. :::note 1 Ocak 2022'den itibaren Google, bu programdan bağımsız olarak tüm otomatik yenilenen aboneliklerden %15 komisyon almaktadır. İndirimli Hizmet Ücreti programı ağırlıklı olarak abonelik dışı uygulama içi satın alımları ve ücretli uygulamaları kapsamaktadır. ::: Program üyelerinin doğru gelir hesaplamaları ve entegrasyon event işlemleri için **Adapty ayarlarını değiştirmeleri** gerekmektedir. Bu makale şunları açıklar: * [Uygulamanız İndirimli Hizmet Ücreti programına kayıtlıysa Adapty nasıl kurulur](#configure-adapty) * [Mağaza komisyonunu azaltmak istiyorsanız programa nasıl kaydolunur](#enroll-in-the-program) ## Adapty'yi Yapılandırın \{#configure-adapty\} Adapty, indirimli komisyon oranını [analitik](analytics) ve [entegrasyon etkinliklerinize](analytics-integration) uygulayabilir. Bunu etkinleştirmek için her uygulama için Azaltılmış Hizmet Ücreti durumunuzu belirtin. :::warning Adapty'deki Azaltılmış Hizmet Ücreti durumunuzu **kaydolur kaydolmaz** yapılandırın. Geç yapılan değişiklikler, daha önce iletilmiş webhook etkinliklerini yeniden yazamaz ([ayrıntılar](#retroactive-setting-changes)). ::: 1. [**App Settings** → **General**](https://app.adapty.io/account) sayfasını açın. 2. **Reduced Service Fee** bölümünü bulun. 3. **Add period** seçeneğine tıklayın. 4. Üyelik başlangıç tarihini seçin. 5. Bir bitiş tarihi seçin ya da bu durumu süresiz olarak uzatmak için **At the current moment** onay kutusunu etkinleştirin. [Yıllık kazancınız 1 milyon ABD dolarını aşarsa](#exceeding-the-threshold) bitiş tarihini güncelleyebilirsiniz. 6. **Apply** seçeneğine tıklayın. Üyelik durumu yalnızca **belirttiğiniz tarih aralığı için** geçerlidir. Program her takvim yılının başında sıfırlanır. * Yeni bir üyelik dönemi eklemek için **Add period** seçeneğine tıklayın. * Bu durumu süresiz olarak uzatmak için **At the current moment** onay kutusunu etkinleştirin. Yapılandırmanızı doğrulamak için [Gelir grafiğini](revenue) açın ve **Proceeds after store commission** seçeneğini belirleyin. Gösterilen gelirin indirimli komisyon oranını yansıtıp yansıtmadığını kontrol edin. ## Programa Kaydolma \{#enroll-in-the-program\} ### Uygunluk gereksinimleri \{#eligibility-requirements\} Google, uygunluğu <InlineTooltip tooltip="Account Group">Kazançları birlikte hesaplanan bir geliştirici hesabı grubu. Geliştirici Hesabınızı Birincil Geliştirici Hesabı olarak belirlemeniz ve ilgili tüm hesapları gruba bağlamanız gerekir.</InlineTooltip> içindeki tüm hesaplarınızdaki **yıllık kazançlarınıza** göre belirler. %15 oranı, birleşik yıllık kazancın ilk 1 milyon ABD doları için geçerlidir. Bu eşiği aşan kazançlar %30 oranında ücretlendirilir. ### Kaydolmadan önce \{#before-you-enroll\} Şunları yaptığınızdan emin olun: - Bir [ödeme profili](https://support.google.com/googleplay/android-developer/answer/10632485) oluşturulmuş olsun - Tüm İlişkili Geliştirici Hesaplarınızı listeleyebiliyor olun ### Kayıt \{#enrollment\} 1. [Google Play Console](https://play.google.com/console/)'a gidin. 2. Bir Hesap Grubu oluşturun ve Geliştirici Hesabınızı Birincil Geliştirici Hesabı olarak belirleyin. 3. İlişkili Geliştirici Hesaplarını gruba bağlayın. 4. İndirimli Hizmet Ücreti programı koşullarını kabul edin. Bu adımları tamamladıktan sonra Google sizi otomatik olarak kaydeder. Manuel inceleme veya onay e-postası gelmez. Ayrıntılı talimatlar için Google'ın [kayıt kılavuzuna](https://support.google.com/googleplay/android-developer/answer/10632485) bakın. ### Eşiği aşma \{#exceeding-the-threshold\} Birleşik yıllık kazancınız 1 milyon ABD dolarını geçtiğinde Google, o takvim yılının geri kalanında eşiği aşan kısım için %30 komisyon uygular. :::important Yıllık kazancınız 1 milyon ABD dolarını aşarsa Adapty ayarlarındaki çıkış tarihini **hemen güncelleyin**. Aksi takdirde Adapty, komisyonu indirimli orandan hesaplamaya devam eder. ::: Program her takvim yılının başında sıfırlanır. Bir yılda kazancınız 1 milyon ABD dolarını aşsa bile ertesi yıl ilk 1 milyon ABD doları için %15 oranı otomatik olarak yeniden uygulanır. Yeniden kayıt gerekmez. Daha fazla bilgi için [resmi program koşullarını](https://support.google.com/googleplay/android-developer/answer/112622?hl=en) okuyun. ## Geriye dönük ayar değişiklikleri \{#retroactive-setting-changes\} Adapty'de indirimli komisyon durumunuzu geriye dönük geçerlilik tarihiyle değiştirdiğinizde, yeni komisyon oranı Adapty'nin verilerinde farklı zamanlamalarda görünür: | Oranın göründüğü yer | Oranı değiştirdikten sonra ne olur | | --- | --- | | Analytics kontrol paneli (Revenue, Proceeds, MRR, ARR) | Adapty, günlük yeniden hesaplama çalıştığında yeni oranı 24 saat içinde uygular. | | S3, GCS ve BigQuery dışa aktarımları | Adapty, yeni oranı bir sonraki zamanlanmış dışa aktarımda uygular. | | Halihazırda iletilmiş webhook olayları | Adapty, webhook olaylarını iletildikten sonra değiştiremez. Bu olaylar eski oranı korur. | Veri ambarınız webhook olaylarından gelen gelir verilerini depoluyorsa, bu kayıtlar eski komisyon oranını korur. Mutabakat sağlamak için etkilenen dönemi analytics kontrol panelinden alın ya da S3, GCS veya BigQuery'ye yeni bir dışa aktarım oluşturun. --- # File: google-play-quota-increase --- --- title: "Google Play Developer API kota artışı talep etme" description: "Geçmiş verileri içe aktarma sırasında veya geniş abone tabanı nedeniyle varsayılan limiti aşarsanız Google Play Developer API için kota artışı talep edin." --- Adapty, satın almaları doğrulamak ve abonelik verilerini senkronize etmek için [Google Play Developer API](https://developers.google.com/android-publisher)'sini kullanır. Bu API için varsayılan kota dakikada 3.000 sorgudur. Uygulamanız bu limiti aşarsa Google size bir e-posta bildirimi gönderir. Bu durum genellikle [geçmiş veri içe aktarımları](importing-historical-data-to-adapty) sırasında veya çok sayıda aktif abonesi olan uygulamalarda yaşanır. Kesintileri önlemek için büyük bir içe aktarma işlemi yapmadan önce ya da kota aşıldığına dair bir bildirim aldıysanız Google'dan kota artışı talep edin. ## Başlamadan önce \{#before-you-start\} Henüz yapmadıysanız [Gerçek Zamanlı Geliştirici Bildirimlerini (RTDN)](enable-real-time-developer-notifications-rtdn) etkinleştirin. RTDN, abonelik güncellemelerini yoklama yerine push bildirimleri aracılığıyla iletir; bu da API tüketimini azaltır. RTDN etkin değilse Google kota artışı taleplerini reddedebilir. ## Gerekli bilgileri toplayın \{#gather-required-information\} Talep formunu açmadan önce şu değerleri hazırlayın: - **Developer Account ID**: Bulmak için [Google Play Console](https://play.google.com/console/)'da **Settings > Developer account > Account details** bölümüne gidin. ID, sayfanın en üstünde listelenir. - **Uygulama paket adı**: Android uygulamanızın paket adı (örneğin, `com.example.app`). Google Play Console'da uygulamanızın **Dashboard** sayfasında bulabilirsiniz. - **Google Cloud proje numarası**: Bulmak için [Google Cloud Console](https://console.cloud.google.com/)'da projenizi seçin. Proje numarası **Dashboard** sayfasında yer alır. ## Kota artışını talep edin \{#request-the-quota-increase\} 1. [Google Play Developer API kota artışı talep formunu](https://support.google.com/googleplay/android-developer/contact/apiqr) açın. 2. Developer Account ID, uygulama paket adı ve Google Cloud proje numaranızı girin. 3. Artış gerektiren API'yi ve kota grubunu seçin. Google'dan kota aşıldığına dair bir e-posta aldıysanız hangi grubun belirtildiğini kontrol edin. 4. Gerekçe alanında, satın almaları doğrulamak ve abonelik verilerini senkronize etmek için API erişimine ihtiyaç duyan bir üçüncü taraf abonelik yönetim hizmeti kullandığınızı açıklayın. 5. Talep edilen kota için ihtiyacınız olan miktarı girin. Ne kadar talep edeceğinizden emin değilseniz, [Google Cloud Console](https://console.cloud.google.com/)'da **IAM & Admin > Quotas** bölümünden mevcut kullanımınızı kontrol edin ("Google Play Android Developer API" için filtreleyin), ardından kullanım verilerinizi ve içe aktarmayı planladığınız geçmiş kayıt sayısını [support@adapty.io](mailto:support@adapty.io) adresine gönderin; doğru miktarı belirlemenize yardımcı olalım. 6. Formu gönderin. Google kota artışı taleplerini genellikle birkaç iş günü içinde işleme alır. --- # File: prepare-your-app-for-store-review --- --- title: "Uygulamanızı mağaza incelemesine hazırlayın" description: "Uygulamanızın App Store ve Google Play Store'da onaylanması için tavsiyeler" --- Bu makale, mağazaların uygulama gönderimleri inceleme sürecini açıklamakta ve uygulamanızın daha hızlı onaylanması için ipuçları sunmaktadır. Bilgiler resmi gönderim yönergelerinden alınmıştır: * [App Store gönderim yönergeleri](https://developer.apple.com/app-store/review/guidelines/) * [Google Play Store gönderim yönergeleri](https://play.google/developer-content-policy/) :::important Her iki mağaza da benzer bir inceleme sürecini izler. Bir politika yalnızca mağazalardan biri için geçerliyse, makalede mağaza adı belirtilir. ::: Adapty kullanıcıları, [paywall'lar ve uygulama içi satın almalar](#iap-related-requirements) konusundaki uyumluluk sorunlarına özellikle dikkat etmelidir. Bunlar, uygulamaların reddedilmesinin en yaygın nedenleri arasındadır. ## Başlamadan önce \{#before-you-begin\} Uygulamanızın gönderime hazır olduğunu doğrulayın. Adapty, uygulamanızı yayına hazırlamak için bir [yayın kontrol listesi](release-checklist) sunar. Google Play Store, ilk kez yayıncı olacakların başvuru öncesinde [uygulamayı test etmesini](https://support.google.com/googleplay/android-developer/answer/14151465?hl=en) zorunlu kılar. Test en az 12 kişiyi kapsamalı ve ardışık en az 14 gün sürmeli. Bu gereklilik, Google'ın inceleme ekibine ulaşan hatalı uygulama sayısını azaltmak amacıyla 2025 yılında getirildi. ## İnceleme sürecine genel bakış \{#review-process-overview\} #### 1. Adım: Otomatik tarama \{#step-1-the-automated-screening\} App Store ve Google Play Store, benzer iki aşamalı bir inceleme süreci izler. Gönderimin hemen ardından uygulamanız birkaç saate kadar sürebilen otomatik bir taramadan geçer. Her iki mağaza da uygulamanızı kötü amaçlı yazılımlara karşı tarar; Google bu sürece özellikle büyük önem verir. Şüpheli sunucularla iletişim ve kullanıcı verilerine izinsiz erişim gibi kötü amaçlı davranış göstergelerini arar. Uygulamanız potansiyel olarak zararlı bulunursa işaretlenir ve bir insan güvenlik analistine iletilir. [Google Play Protect belgeleri](https://developers.google.com/android/play-protect/cloud-based-protections#machine-learning), bu adımda gerçekleştirilen kontrollerin yaklaşık bir listesini içermektedir. Mağazalar ayrıca gerekli meta verilerin varlığını, zararlı veya ciddi ölçüde eski bağımlılıkların bulunmadığını ve derlemenizin bütünlüğünü de doğrular. #### 2. Adım: İnsan incelemesi \{#step-2-the-human-review\} Uygulamanız otomatik taramayı geçtikten sonra bir insan inceleyici tarafından değerlendirilir. Bu adım, uygulamanızın karmaşıklığına ve mevcut inceleme kuyruğuna bağlı olarak birkaç güne kadar sürebilir. Hassas veri işleyen uygulamalar daha uzun süre incelenir. ## Genel gereksinimler \{#general-requirements\} ### Kararlılık \{#stability\} İnceleme sırasında çöken uygulamalar reddedilir. İncelemeciler kasıtlı olarak güvenilmez ağ koşullarını simüle edebilir; bu nedenle uygulama bu koşullarla iyi başa çıkabilmelidir. ### Eksiksizlik \{#completeness\} Apple ve Google, mağaza içeriklerinde *eksiksizlik* ("minimum işlevsellik") şartı arar. * Yer tutucular, "yakında" ekranları ve bozuk özellikler, iOS uygulamalarının reddedilmesine yol açar. * Google, özellikle uygulamanız [Erken Erişim](https://knowledge.workspace.google.com/admin/users/access/turn-early-access-apps-on-or-off-for-users) kapsamındaysa [daha esnek](https://support.google.com/googleplay/android-developer/answer/9898783?hl=en) davranır. * Her iki mağaza da işlevselliği çok az olan veya hiç olmayan uygulamaları **reddeder**. Bu, tek bir resim, PDF dosyası veya web sayfası görüntüleyen uygulamaları da kapsar. Eksik içerik de aynı kategoriye girer. * Uygulama, tanıttığınız işlevi yerine getirmiyorsa reddedilir. * Kontrol panelinizde bir uygulama içi satın alma yapılandırıp derlemede yer vermezseniz uygulama reddedilir. ### Meta veri doğruluğu \{#metadata-accuracy\} Açıklama, ekran görüntüleri ve diğer meta verilerdeki yanıltıcı, yanlış veya tutarsız bilgiler reddedilmeye yol açabilir. Mağaza listenizi gelecekteki uygulama özelliklerini tanıtmak için kullanmayın. Uygulama genel kamuya yönelik değilse incelemeci, iş akışlarını açıklayan ek belgeler arayacaktır. Uygulamanın meta verilerine açık talimatlar ekleyin. ### İçerik derecelendirmesi \{#content-rating\} Uygulamanızdaki içerik, beyan edilen derecelendirmeyle uyuşmalıdır. ### Hukuki gereklilikler \{#legal-aspects\} * Uygulamanızın gizlilik politikasına uygulama içinden erişilebilmeli. Paywall builder'ın [bağlantı düğmesini](paywall-buttons#links) kullanabilirsiniz. * Kullanıcıların tüm hukuki sözleşmeleri yürürlüğe girmeden **önce** okuyup kabul etmelerini isteyin. * Uygulamanızdaki reklamların varlığını açıkça belirtin. Bunu yapmamak reddedilmeyle sonuçlanabilir. * iOS uygulamanız uygulama içi satın alma içeriyorsa App Store Connect kontrol panelinizde **Paid Apps Agreement**'ı kabul etmeniz gerekir. ### Kimlik doğrulama \{#authentication\} Uygulamanızın içeriğinin bir kısmı yalnızca kimlik doğrulamasının ardından erişilebiliyorsa mağaza incelemecisi için geçerli erişim kimlik bilgileri sağlayın. İçeriğe tam olarak erişilememesi reddedilmeye yol açar. Uygulamanız kullanıcıların hesap oluşturmasına izin veriyorsa hesabı silmelerine de olanak tanımalıdır. Kullanıcıları e-posta tabanlı destek veya bir web sitesine yönlendirmek bu gereksinimi karşılamaz. ### Erişim ve gizlilik \{#access-and-privacy\} Uygulamanın meta verilerinde talep edilen her iznin nedeni açıkça belirtilmelidir. En hassas izinler (örneğin, kısa mesajlara ve arama günlüklerine erişim) video gösterimi gerektirebilir. Aynı ilke hassas kullanıcı verileri için de geçerlidir: talep ediyorsanız nedenini açıklayın. ## Uygulama içi satın alma ile ilgili gereksinimler \{#iap-related-requirements\} İş politikası ihlalleri, uygulama reddetme nedenlerinin en yaygınları arasındadır. Uygulamanızın birincil para kazanma yöntemi abonelikler ve uygulama içi satın almalarsa daha sıkı bir denetimle karşılaşırsınız. ### Paywall gereksinimleri \{#paywall-requirements\} Uygulama incelemecileri, anlaşılması kolay ve açık paywall'lar bekler. Kullanıcı manipülasyonundan şüphelenilirse uygulama reddedilir. Birden fazla incelemede yanıltıcı uygulamalara dair kanıt bulunursa hesabınız devre dışı bırakılabilir ve uygulamanız [askıya alınabilir](https://support.google.com/googleplay/android-developer/community-guide/287283557/app-suspended-for-repeated-rejections?hl=en). Google Play, tüm uygulamalarınızın silinmesine yol açabilecek bir [ihlal sistemi](https://support.google.com/googleplay/android-developer/answer/9899234?hl=en) kullanır. Paywall tasarımınızda şu kurallara uyun: - **Şeffaf ve net olun.** Kullanıcıyı satın almaya yönlendirmeden önce ürünlerin tam fiyatını, fatura sıklığını, avantajlarını ve iptal koşullarını gösterin. Tek seferlik satın almalar ile yinelenen ödeme gerektiren ürünleri net biçimde birbirinden ayırt edin. Bir üründe ücretsiz deneme varsa süresini ve koşullarını açıkça belirtin. Kullanıcıyı yanıltmak amacıyla kasıtlı olarak kafa karıştırıcı bir dil kullanmayın. - **Tutarlı olun.** Ürün fiyatları App Store listenizde, uygulama içi ekranlarda, abonelik yönetim ekranlarında ve pazarlama içeriğinde eşleşmelidir. Ne kadar küçük olursa olsun her fiyat uyuşmazlığı reddedilmeye gerekçe oluşturur. Adapty'nin Paywall Builder'ı, paywall'ınızdaki fiyatları App Store Connect ürününüzle otomatik olarak eşitler. Paywall'ınızı elle kodladıysanız her ürünün fiyatını veri dizisinden [çekmeniz](fetch-paywalls-and-products) gerekir. - **Tüm kademeleri eşit biçimde gösterin.** En pahalı seçeneği önceden seçili bırakmayın, ucuz seçenekleri gizlemeyin. - **"Karanlık örüntülerden" kaçının.** Sahte bir aciliyet veya kıtlık hissi yaratmayın. Ücretsiz özellikleri kasıtlı olarak kullanışsız veya bulmak zor hale getirerek kullanıcıları satın almaya zorlamayın. ### Erişim güvencesi \{#access-guarantee\} Uygulama, kullanıcıların satın aldıklarına erişim hakkını garanti etmelidir. * **Anlık erişim** Başarılı bir satın alma, ürüne erişimi gözle görülür bir gecikme olmadan hemen açmalıdır. Ödeme yetkilendirmesinin ara durumları hata vermemeli veya kullanıcı deneyimini bozmamalıdır. Başarılı bir satın alma, paywall'ı hemen gizlemelidir. Satın alma işleminin ardından paywall'ı göstermeye devam ederseniz kullanıcının ödediği içeriğe erişimini engellemiş olursunuz. * **Erişim geri yükleme** Kullanıcının yeni bir cihazdan ürüne erişimini geri yükleyebilmesi gerekir. Geri yükleme düğmesini görünür bir yere yerleştirin. Paywall'ınızı [Flow Builder](adapty-flow-builder) ile oluşturduysanız, geri yükleme düğmesi otomatik olarak geri yükleme işlemini başlatır. [Manuel paywall uyguladıysanız](ios-implement-paywalls-manually), [restorePurchases](restore-purchase) metodunu tetikleyen bir kod ekleyin. SDK'yı [gözlemci modunda](observer-vs-full-mode) kullanmıyorsanız Adapty, kullanıcının access level'ını geri yükler. Uygulama, ürünün mağaza sayfasından veya uygulama mağazasının başka bir yerinden yapılan uygulama içi satın almaları tanıyabilmelidir. ### Uygun ödeme yöntemleri \{#appropriate-payment-methods\} Her iki mağaza da uygulama içi satın almalarla fiziksel mal satışını yasaklar ve çoğu dijital içerik için mağaza içi ödemeyi zorunlu kılar. Mağaza içi ödeme zorunluluğu ABD ve AB dahil bazı coğrafi yetki alanlarında geçerli değildir. Ülkeye bağlı olarak [mağaza içi ödemeyi tamamen devre dışı bırakabilir](https://support.google.com/googleplay/android-developer/answer/16497028) veya [kullanıcıya uygulama mağazası ödemesi ile alternatif ödeme arasında seçenek sunabilirsiniz](https://support.google.com/googleplay/android-developer/answer/13821247). E-kitap okuyucuları veya tanışma uygulamaları gibi bazı uygulama kategorileri, bu bölgelerin dışında bile alternatif ödeme yöntemlerine uygun olabilir. Ayrıntılar için mağazaların resmi yönergelerini inceleyin. :::tip [Google'ın](https://support.google.com/googleplay/android-developer/answer/13821247) aksine Apple, alternatif ödeme yöntemlerine izin veren ülkelerin kesin bir listesini sunmaz. Yeni yetki alanlarının benzer yasalar çıkarmasıyla bu imkân genişlemeye devam edecektir. Devam etmeden önce kendi ülkenize özgü belgeleri okuyun. ::: Her iki mağazanın da ödeme sağlayıcı entegrasyonlarına ilişkin yönergeleri uyguladığını ve bu hizmetleri kullanan işlemler için komisyon almaya devam ettiğini unutmayın. ## Reddedilmeyle başa çıkma \{#handling-rejection\} Uygulamanız reddedilirse incelemeci hangi yönergelerin ihlal edildiğini belirtir. İlgili yönergeyi baştan sona okuyun ve düzeltin: * [App Store başvuru yönergeleri](https://developer.apple.com/app-store/review/guidelines/) * [Google Play Store başvuru yönergeleri](https://play.google/developer-content-policy/) Reddin haksız olduğunu düşünüyorsanız itiraz etme hakkınız vardır. Uyumu kanıtlayan belgeler sunun ve mağazayla iletişime geçin. * Uygulama incelenirken güncelleme yapmayın. * Her başvuruda farklı bir incelemeci atanabilir. Bu durum lehinize veya aleyhinize işleyebilir. * Sorunları tek tek düzeltmeyin. Tüm düzeltmeler tamamlandığında uygulamayı yeniden incelemeye gönderin. * Google Play, uygulamanızı politika ihlalleri nedeniyle reddettiyse söz konusu verileri, duraklatılmış veya etkin olmayan izler dahil tüm izlerde güncelleyin. * Sonraki incelemeler genellikle ilkinden daha kısa sürer. * Kritik hatalar ve son teslim tarihleri için hızlandırılmış inceleme talep edilebilir — bunu gerekmedikçe kullanmayın. ## İnceleme sonrası: sürekli izleme \{#after-the-review-continuous-monitoring\} Her iki uygulama mağazası da uygulamanızı inceleme sürecini geçtikten sonra da izlemeye devam eder. Uygulamanızın işlevi onaydan sonra değişirse (örneğin, dinamik olarak yüklenen kod nedeniyle) işaretlenir ve listeden kaldırılır. Yoğun olumsuz kullanıcı geri bildirimi de ek denetime gerekçe oluşturur. 2024-2025 yılları arasında Google, ortalama kaliteyi artırmak amacıyla Play Store uygulamalarının [%47'sini kaldırdı](https://techcrunch.com/2025/04/29/google-play-sees-47-decline-in-apps-since-start-of-last-year/). Uygulamanızı terk etmek de risk taşır. [Google](https://www.cnet.com/tech/mobile/google-play-store-will-hide-apps-that-havent-been-updated-in-years/) ve [Apple](https://developer.apple.com/support/app-store-improvements/#:~:text=Developers%20of%20apps%20that%20have,launch%20will%20be%20removed%20immediately.) güncelleme veya indirme almayan uygulamaları listeden çıkarır. ## Ayrıca bakınız \{#see-also\} * [Sandbox testi](test-purchases-in-sandbox) * [Yayın kontrol listesi](release-checklist) --- # File: firebase-apps --- --- title: "Firebase uygulamaları" description: "Mobil uygulamanız için kullanıcı analitiğini ve abonelik takibini geliştirmek amacıyla Firebase'i Adapty ile entegre edin." --- Bu sayfa, uygulamanızın Firebase üzerinde çalışması durumunda Adapty'nin entegrasyonunu anlatmaktadır. :::note Başlarken Bunlar Adapty'nin çalışması için gereken tüm adımlar değil, yalnızca Firebase entegrasyonu için bazı yararlı ipuçlarıdır. Adapty'yi uygulamanıza entegre etmek istiyorsanız önce [Hızlı Başlangıç Kılavuzu](quickstart)'nu okumalısınız. ::: ## Kullanıcı Kimliği \{#user-identification\} Firebase auth kullanıyorsanız, kullanıcılarınızı Firebase ile Adapty arasında senkronize tutmanıza yardımcı olacak bir kod parçacığı aşağıda verilmiştir. Bunun yalnızca bir örnek olduğunu ve uygulamanızın kimlik doğrulama özelliklerini göz önünde bulundurmanız gerektiğini unutmayın. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS with Firebase" default> ```swift showLineNumbers @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Configure Adapty before Firebase Adapty.activate("YOUR_API_KEY") Adapty.delegate = self // Configure Firebase FirebaseApp.configure() // Add state change listener for Firebase Authentication Auth.auth().addStateDidChangeListener { (auth, user) in if let uid = user?.uid { // identify Adapty SDK with new Firebase user Adapty.identify(uid) { error in if let e = error { print("Sign in error: \(e.localizedDescription)") } else { print("User \(uid) signed in") } } } } return true } } extension AppDelegate: AdaptyDelegate { // MARK: - Adapty delegate func didReceiveUpdatedPurchaserInfo(_ purchaserInfo: PurchaserInfoModel) { // You can optionally post to the notification center whenever // purchaser info changes. // You can subscribe to this notification throughout your app // to refresh tableViews or change the UI based on the user's // subscription status NotificationCenter.default.post(name: NSNotification.Name(rawValue: "com.Adapty.PurchaserInfoUpdatedNotification"), object: purchaserInfo) } } ``` </TabItem> <TabItem value="kotlin" label="Android with Firebase" default> ```kotlin showLineNumbers class App : Application() { override fun onCreate() { super.onCreate() // Configure Adapty Adapty.activate(this, "YOUR_API_KEY") Adapty.setOnPurchaserInfoUpdatedListener(object : OnPurchaserInfoUpdatedListener { override fun onPurchaserInfoReceived(purchaserInfo: PurchaserInfoModel) { // handle any changes to subscription state } }) // Add state change listener for Firebase Authentication FirebaseAuth.getInstance().addAuthStateListener { auth -> val currentUserId = auth.currentUser?.uid if (currentUserId != null) { // identify Adapty SDK with new Firebase user Adapty.identify(currentUserId) { error -> if (error == null) { //success } } } else { Adapty.logout { } } } } } ``` </TabItem> </Tabs> --- # File: refund-saver --- --- title: "Refund Saver" description: "Refund sayısını azaltmak ve geliri artırmak için Adapty Refund Saver'ı kullanın." --- Bir kullanıcı iade talebinde bulunduğunda, Apple bir soruşturma başlatır. **İadenin haklı olup olmadığına** karar vermek için geliştiriciden söz konusu kullanıcının etkinliğine ilişkin bilgi ister. Bu kanıt olmadan, yoğun biçimde kullanılmış bir abonelik bile büyük ihtimalle iade edilir. **Refund Saver**, Apple'ın tüketim taleplerini [otomatik olarak](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information-v1) yanıtlayarak gelirinizi korur ve haksız talepler için **ret olasılığını artırır**. Otomatik yenilenen abonelikler, tek seferlik abonelikler, consumable'lar ve non-consumable'lar (süresiz ürünler dahil) gibi tüm Apple uygulama içi satın alma türlerinde çalışır. ## Refund Saver nasıl çalışır \{#how-refund-saver-works\} 1. Bir kullanıcı iade talebi başlattığında, App Store işlem ve kullanım ayrıntılarını isteyen bir bildirim gönderir. Yanıtı **görmezden gelirseniz** veya **geciktirirseniz**, Apple büyük ihtimalle **iadeyi onaylar**. 2. Adapty Refund Saver bu bildirimleri otomatik olarak işler ve Apple'a gerekli verileri sağlar. Bu otomasyon, gereksiz iadelerin önüne geçerken zamandan tasarruf etmenizi ve gelirinizi korumanızı sağlar. 3. Adapty her sonucu — iade edildi veya reddedildi — kaydeder. Bu veriler, Kontrol Paneli'ndeki Refund Saver analizlerini besler. :::info Refund Saver ile iade taleplerinden elde edilen gelirin %40'a kadarını kurtarabilirsiniz. ::: ## Refund Saver kullanım gereksinimleri \{#requirements-to-use-refund-saver\} Bu özelliği kullanmak için aşağıdaki ön koşulları karşıladığınızdan emin olun: 1. **App Store Connect'te Gizlilik Politikanızı güncelleyin:** Uygulamanızın Gizlilik Politikası, tüketim verilerinin toplanmasını ve kullanımını açıkça belirtmelidir. Bu sayede kullanıcılar uygulamayı indirmeden önce gizlilik uygulamalarınızdan haberdar olur. Yönlendirme için [Apple'ın Uygulama Gizlilik Ayrıntıları](https://developer.apple.com/app-store/app-privacy-details/) sayfasına bakın. 2. **Uygulamanızda veri paylaşımı için kullanıcı onayı alın:** Apple, kişisel verileri Apple ile paylaşmadan önce kullanıcıdan geçerli onay almanızı zorunlu kılmaktadır. Kullanıcı verilerini Apple ile siz paylaşacağınız için bu onayı almak sizin sorumluluğunuzdadır. Daha fazla ayrıntı için Apple'ın [yönergelerine](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information) bakın. 3. **Server Notifications V2'yi etkinleştirin:** Apple Geliştirici hesabınızda Server Notifications V2'nin etkin ve Adapty'de doğru yapılandırılmış olduğundan emin olun; V1 bildirimleri desteklenmemektedir. Henüz etkinleştirmediyseniz [App Store sunucu bildirimlerini etkinleştirme](enable-app-store-server-notifications) kılavuzundaki adımları izleyin. ## Refund Saver'ı Etkinleştirme \{#turn-on-refund-saver\} 1. Adapty Kontrol Paneli'nde [Refund Saver](https://app.adapty.io/refund-saver) bölümünü açın. 2. Özelliği etkinleştirmek için **Turn on Refund Saver** düğmesine tıklayın. ## Varsayılan iade davranışını ayarlama \{#set-a-default-refund-behavior\} Apple, geliştiricilerin her iade talebine yanıt verirken tercih ettikleri sonucu belirtmesine olanak tanır. Bu ayarın amacı, yalnızca adil iadelerin yapılmasını sağlamak için iade taleplerini reddetme ile kabul etme arasında doğru dengeyi bulmaktır. Bu ayarın yalnızca sonucu etkilemek için kullanıldığını, nihai kararın yine de Apple'a ait olduğunu unutmayın. Adapty bu tercihi ayarlamayı destekler; ancak her iade talebi için aynı değeri kullanır. 1. Tercihinizi değiştirmek için **Edit refund preference** seçeneğine tıklayın. 2. **Edit refund preference** penceresinde **Default refund request preference** seçeneğinizi belirleyin: | Seçenek | Açıklama | | -------------------------------------------- | ------------------------------------------------------------ | | Always decline | (varsayılan) Bu, varsayılan seçenektir ve genellikle iade taleplerini en aza indirmek için en iyi sonuçları verir. | | Decline first refund request, grant all next | Refund Saver'ın karşılaştığı her işlem için başlangıçta Apple'dan iadeyi reddetmesi istenir. Ancak aynı işlem tekrar görünürse, Refund Saver her zaman iadenin onaylanmasını önerir. Bu yaklaşım, haksız iade redlerinden kaynaklanan kullanıcı hayal kırıklığını en aza indirmeye yardımcı olur — kullanıcılar iadeyi yeniden talep edebilir ve büyük ihtimalle alabilirler. | | Always refund | Apple'ın her iade talebini onaylamasını önerir. | | No preference | Apple'a herhangi bir öneri sunmaz. Bu durumda Apple, sizin ayarlarınızdan bağımsız olarak kendi iç politikaları ve kullanıcı geçmişine göre iade sonucunu belirler. Bu seçenek en tarafsız yaklaşımı sunar. | ## Kontrol panelinde belirli bir kullanıcı için geri ödeme davranışını ayarlayın \{#set-refund-behavior-for-a-specific-user-in-the-dashboard\} Tüm uygulama için varsayılan Refund Saver davranışını yapılandırmış olsanız bile, belirli kullanıcılar için bireysel tercihler belirlemek isteyebilirsiniz. Adapty Kontrol Paneli'nde bunu kullanıcının profilinden yapabilirsiniz. Sol alt köşede yer alan **Refund Saver Preferences** bölümünü kullanın. :::note Kullanıcı başına tercihler, "İlk geri ödeme talebini reddet, sonraki tüm talepleri onayla" davranışı da dahil olmak üzere uygulama düzeyindeki varsayılanı geçersiz kılar. ::: ## SDK'da belirli bir kullanıcı için iade davranışını ayarlama \{#set-refund-behavior-for-a-specific-user-in-the-sdk\} Kullanıcının belirli eylemlerine bağlı olarak her kurulum için iade tercihini uygulama kodunuzda ayrı ayrı ayarlayabilirsiniz. Tercihi ayarlamak için aşağıdaki kod parçacığını kullanın: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (3.4.1+)" default> ```swift showLineNumbers code do { try await Adapty.updateRefundPreference(<PREFERENCE_VALUE>) // possible values: .noPreference, .grant, .decline } catch { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter (3.4.0+)" default> ```javascript showLineNumbers code try { // possible values: AdaptyRefundPreference.noPreference, AdaptyRefundPreference.grant, AdaptyRefundPreference.decline await Adapty().updateRefundPreference(<PREFERENCE_VALUE>); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="rn" label="React Native (3.4.0+)" default> ```typescript showLineNumbers try { await adapty.updateRefundPreference(<PREFERENCE_VALUE>); // possible values: RefundPreference.NoPreference, RefundPreference.Grant, RefundPreference.Decline } catch (error) { // handle the `AdaptyError` } ``` </TabItem> <TabItem value="unity" label="Unity (3.3.0+)" default> ```csharp showLineNumbers Adapty.UpdateAppStoreRefundPreference(<PREFERENCE_VALUE>, (error) => { if (error != null) { // handle the error return; } }); ``` </TabItem> </Tabs> :::note Sunucu tarafı API'sini kullanarak da [bireysel iade tercihi ayarlayabilirsiniz](api-adapty/operations/setRefundSaverSettings): - Tercih ayarı, kullanıcının bir düğmeye tıklaması gibi doğrudan istemci etkileşimlerine bağlıysa SDK'yı kullanın. - Sunucu taraflı işlem yapmanız gerektiğinde veya uygulama mimarinizle daha iyi uyum sağladığında API'yi kullanın. ::: ## Kullanıcı onayı alma \{#obtain-user-consent\} Veri paylaşımı için kullanıcı onayını nasıl toplayacağınız size kalmış; ancak Apple, kişisel verileri paylaşmadan önce geçerli kullanıcı onayı zorunlu kılmaktadır. Apple, **opt-in yaklaşımı** kullanmanızı önerir; bu yaklaşım, verilerin nasıl kullanılacağını açıklayan ve kullanıcıdan açık bir eylem gerektiren uygulama içi istemler içerir. Kullanıcı istemi yoksayarsa veya reddederse onay vermiş sayılmaz. Daha fazla ayrıntı için Apple'ın [yönergelerine](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information) bakın. Uygulamanız için açık onay almanız pratik değilse, **vazgeçme (opt-out) yaklaşımını** değerlendirebilirsiniz. Bu yaklaşım, Kullanım Koşulları'nıza bir veri paylaşım maddesi ekleyerek kullanıcıların koşulları kabul ederek veri paylaşımını onayladığını belirtmeyi içerir. Kullanıcıların onaylarını nasıl geri çekebileceklerini açıkça belirttiğinizden emin olun. Aşağıda, paylaşabileceğiniz veri türlerini de içeren bir vazgeçme yaklaşımı örnek maddesi yer almaktadır. Bu yalnızca kendi metninizi oluştururken size yol göstermek için hazırlanmış bir örnektir. Geçerli tüm yasalara ve Apple'ın gereksinimlerine uygunluğu sağlamak sizin sorumluluğunuzdadır. *"Uygulama içi bir satın alma için iade talebi aldığımızda, kullanıcının uygulama içi satın alma etkinliğine ilişkin bilgileri Apple ile paylaşabiliriz. Bu bilgiler; uygulamanın kurulumundan bu yana geçen süre, toplam uygulama kullanım süresi, anonim bir hesap tanımlayıcısı, uygulama içi satın alımın tamamen tüketilip tüketilmediği, deneme süresi içerip içermediği, harcanan toplam tutar ve iade edilen toplam tutar gibi ayrıntıları kapsayabilir."* Seçtiğiniz yaklaşıma göre **Edit refund preferences** menüsündeki **Default consent policy** seçeneğini ayarlayın: <p> </p> | Seçenek | Açıklama | | ------- | ------------------------------------------------------------ | | Opt-out | (varsayılan) Adapty kullanıcının onay durumunu bilmiyorsa onayın **verildiğini** varsayar ve Refund Saver iade ile ilgili verileri Apple ile **paylaşır**. | | Opt-in | Adapty kullanıcının onay durumunu bilmiyorsa onayın **verilmediğini** varsayar ve Refund Saver Apple ile **hiçbir veri paylaşmaz**. Bu, Apple'ın önerdiği yaklaşımdır. | ## SDK'da kullanıcı onayını güncelleme \{#update-user-consent-in-the-sdk\} Belirli bir kullanıcının onay verip vermediğini Adapty'ye bildirmek için `updateCollectingRefundDataConsent` metodunu kullanın. Değer, profil başına sunucu tarafında saklandığından yalnızca onay değiştiğinde bu metodu çağırmanız yeterlidir. <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (3.4.1+)" default> ```swift showLineNumbers do { try await Adapty.updateCollectingRefundDataConsent(<CONSENT_VALUE>) // true = onay açıkça verildi, false = onay açıkça iptal edildi } catch { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter (3.4.0+)" default> ```dart showLineNumbers try { // true = kullanıcı onay verdi, false = kullanıcı onayı geri aldı await Adapty().updateCollectingRefundDataConsent(<CONSENT_VALUE>); } on AdaptyError catch (adaptyError) { // hatayı işle } catch (e) { // hatayı işle } ``` </TabItem> <TabItem value="rn" label="React Native (3.4.0+)" default> ```typescript showLineNumbers try { await adapty.updateCollectingRefundDataConsent(<CONSENT_VALUE>); // true = onay açıkça verildi, false = onay açıkça geri alındı } catch (error) { // `AdaptyError` hatasını işle } ``` </TabItem> <TabItem value="unity" label="Unity (3.3.0+)" default> ```csharp showLineNumbers Adapty.UpdateAppStoreCollectingRefundDataConsent(<CONSENT_VALUE>, (error) => { if (error != null) { // handle the error return; } }); ``` </TabItem> </Tabs> :::note Sunucu tarafı API'sini kullanarak da [bireysel veri paylaşım tercihini ayarlayabilirsiniz](api-adapty/operations/setRefundSaverSettings): - Tercih ayarı, kullanıcının bir düğmeye tıklaması gibi doğrudan istemci etkileşimlerine bağlıysa SDK'yı kullanın. - Sunucu taraflı işlem yapmanız gerektiğinde veya uygulama mimarinizle daha iyi uyum sağladığında API'yi kullanın. ::: ## Kullanıcı onayını kontrol etme \{#check-user-consent\} Bir kullanıcının mevcut onay durumunu istediğiniz zaman kontrol edebilirsiniz. Adapty Kontrol Paneli'nde kullanıcının profilini açın ve sol alttaki **Refund Saver Preferences** bölümünde **Allow data sharing** ayarına bakın. :::note Bireysel iade ve paylaşım tercihlerini almak için Server-side API'yi de kullanabilirsiniz: [get individual refund and sharing preferences](api-adapty/operations/getRefundSaverSettings). ::: ## Sınırlamalar \{#limitations\} - **Yalnızca Apple App Store:** Refund Saver, yalnızca Apple App Store'a yapılan iade talepleri için kullanılabilir. Google Play, iadeler için tüketim verisi analizi sunmamaktadır. Google Play'deki iade kararları yalnızca Google'ın politikalarına ve kullanıcının sağladığı bilgilere dayanır. - **Sunucu Bildirimleri V2 gerektirir:** Refund Saver, App Store Server Notifications V1 ile uyumlu değildir. Adapty'de şu anda V1 kullanıyorsanız V2'ye geçmeniz gerekir; ayrıntılar için [App Store sunucu bildirimlerini Adapty'ye gönderme](enable-app-store-server-notifications) kılavuzuna bakın. V2'ye geçmek, daha doğru ve kapsamlı veriler sağlayarak Adapty'deki analizlerinizi de iyileştirecektir. --- # File: meta-create-campaign --- --- title: "Uygulamanızı Meta Ads'de Tanıtın" --- Bu adım adım kılavuzda, uygulamanız için Meta'da nasıl reklam oluşturup yapılandıracağınızı öğreneceksiniz; böylece reklamlarınızı kolayca optimize edebilir ve performanslarını takip edebilirsiniz. ## Meta'da reklamlar nasıl yapılandırılır? \{#how-ads-in-meta-are-structured\} Meta Ads'de reklam verirken üç hiyerarşik düzeyi yapılandırmanız gerekir: - **Kampanya**: Kampanyalar, reklam hedeflerinizi tanımlar. - **Reklam seti**: Reklam setleri, hedef kitlenizi ve yerleşimlerinizi belirler; reklamlarınızın nerede ve kimlere gösterileceğini tanımlar. Her kampanya birden fazla reklam seti içerebilir. - **Reklamlar**: Reklamlar, kullanıcıların gördüğü ve etkileşime geçtiği gerçek içeriklerdir. Her reklam seti birden fazla reklam içerebilir; ancak en iyi performans için reklam seti başına beşten fazla reklam kullanılmaması önerilir. ## Adım 1. Meta Ads Manager Hesabı Oluşturun \{#step-1-create-meta-ads-manager-account\} Meta Ads'e başlamak için bir Facebook İşletme sayfasına ihtiyacınız var; kişisel sayfanızdan reklam veremezsiniz. Bu nedenle işletme sayfanızı Meta Ads iş portföyünüze bağlamanız gerekir: 1. [business.facebook.com](https://business.facebook.com/) adresine gidin. İş portföyünüzde henüz bir işletme sayfanız yoksa eklemeniz gerekir. **Go to settings** seçeneğine tıklayın. 2. Sol kenar çubuğundan **Account > Pages** bölümüne gidin. **Add** seçeneğine tıklayın ve **Add an existing Facebook page** ya da **Create a new Facebook page** seçeneğini belirleyin. Henüz bir işletme sayfanız yoksa [işletme sayfası oluşturma kılavuzuna](https://www.facebook.com/business/help/473994396650734) bakın. 3. İsteğe bağlı olarak, ayarlardaki **Account > Instagram accounts** sayfasından Instagram hesabınızı bağlayın. İşletme sayfanızı bağladıktan sonra devam etmeye hazırsınız. ## Adım 2. Meta Piksel Ekleyin \{#step-2-add-meta-pixel\} Kampanya verilerinizi gelirle ilişkilendirmek ve daha iyi sonuçlar almak için bir Meta pikseline ihtiyacınız olacak. Veri bağlamadan ve piksel oluşturmadan önce şunlara ihtiyacınız var: - Bir işletme sayfası – [**Settings > Accounts > Pages**](https://business.facebook.com/latest/settings/pages) üzerinden iş portföyünüze ekleyin - Bir Business Manager hesabı – iş portföyü üzerinde tam kontrolünüz olmalı - Bir iş e-postası – [**Settings > Business info**](https://business.facebook.com/latest/settings/business_info) bölümünde ayarlanmış olmalı - Bir reklam hesabı – [**Settings > Accounts > Ad accounts**](https://business.facebook.com/latest/settings/ad_accounts) üzerinden iş portföyünüze ekleyin Hazır olduğunuzda bir pixel oluşturun: 1. [**Events Manager**](https://www.facebook.com/events_manager2)'a gidin. **Connect data** düğmesine tıklayın. 2. Veri kaynağı türü olarak **Web**'i seçin. 3. Veri kümenize bir ad verin ve **Create**'e tıklayın. 4. [Adapty Attribution](adapty-user-acquisition) için pixel'in tam kurulumunu tamamlamanıza gerek yoktur. Bu nedenle entegrasyon hakkında soru sorulduğunda, kurulum penceresindeki **x** düğmesine tıklayabilirsiniz; sayfayı yenilediğinizde pixel'iniz listede görünecektir. 5. Veri kümeniz listede göründüğünde kampanya oluşturmaya geçebilirsiniz. ## Adım 3. Kampanya Oluşturun \{#step-3-create-campaign\} Meta Ads Manager'da kampanya oluşturmak için: 1. [Meta Ads Manager](https://adsmanager.facebook.com/adsmanager/manage) sayfasına gidin. **Campaign** sekmesinde **Create** seçeneğine tıklayın. 2. Kampanya hedefi olarak **Sales** seçin ve **Continue** seçeneğine tıklayın. 3. Kampanyanıza **Campaign name** bölümünde bir ad verin. 4. **Budget** bölümünde, **Budget strategy** alanında bütçeyi nasıl kontrol etmek istediğinizi seçin: - **Campaign budget**: Hangi fırsatların en iyi sonucu vereceğinden emin değilseniz en kolay seçenek. Bunu seçerseniz Meta Ads, en iyi performans gösteren reklam setlerine daha fazla bütçe ayırmak için üst performanslıları otomatik olarak tespit eder. Ardından **Daily** veya **Lifetime** bütçeye ihtiyacınız olup olmadığını seçin ve para biriminizde limiti girin. **Daily** bütçe, hâlâ öğrenirken daha fazla esneklik sağlar; böylece küçük miktarlarla başlayıp giderek ayarlayabilirsiniz. Ya da **Schedule budget increase** seçeneğini belirleyerek bütçeyi değer miktarı veya yüzde olarak otomatik artıracak kurallar oluşturabilirsiniz. - **Ad set budget**: Hangi kitlelerin daha fazla veya daha az kampanya bütçesi alacağını manuel olarak belirlemek istiyorsanız bu seçeneği kullanın. Tam olarak emin değilseniz, reklam performansına fayda sağlaması durumunda Meta'nın reklam seti bütçelerini %20'ye kadar otomatik ayarlamasına izin vermek için **Share some of your budget with other ad sets** seçeneğini belirleyebilirsiniz. 5. **Campaign bid strategy** bölümünde hedeflerinize en uygun seçeneği belirleyin: - **Highest volume (default)**: Başlamak için en kolay seçenek. Bunu seçerseniz Meta'nın bütçeniz için en iyi sonuçları elde etmek amacıyla tıklama maliyetini optimize etmesine izin vermiş olursunuz. - **Cost per result goal**: Kıyaslamalarınızı biliyorsanız belirli bir sonuç başına maliyet hedefi belirleyin. - **Bid cap**: Teklif vermeye hazır olduğunuz en yüksek maliyeti belirleyin. 6. Adapty, kapsamlı [A/B testleri](ab-tests) yapmanıza olanak tanır. Ancak gerekirse Meta Ads'de de A/B testlerini etkinleştirebilirsiniz. Meta Ads Manager'daki A/B testleri hakkında daha fazla bilgi edinmek için [buraya](https://www.facebook.com/business/help/1159714227408868) bakın. 7. Şimdi kampanyanıza ilk reklam setini ekleme zamanı. Devam etmek için **Next** seçeneğine tıklayın. ## Adım 4. Reklam Seti Oluşturun \{#step-4-create-ad-set\} Reklam seti oluşturmak için: 1. **Ad set name** alanına reklam setiniz için bir ad verin. 2. **Conversion location** açılır menüsünde **Website** seçin. 3. **Performance goal** alanında, bir açılış sayfanız varsa **Maximize number of landing page views**, kullanıcıları doğrudan mağazaya yönlendiren akıllı bir bağlantı kullanıyorsanız **Maximize number of link clicks** seçeneğini belirleyin. 4. **Dataset** alanında [Adım 2](#step-2-add-meta-pixel)'de oluşturduğunuz veri kümesini seçin. 5. Bir **Conversion event** seçin. Bizim durumumuzda bu büyük ihtimalle **Purchase** veya **Start trial** olacaktır. Veri kümenizde henüz hiç etkinlik olmadığına dair bir uyarı görürseniz endişelenmeyin; bu sadece veri kümenizin yeni olduğu anlamına gelir. 6. Kampanyayı kurarken **Ad set budget** seçtiyseniz, **Daily** veya **Lifetime** bütçeye ihtiyacınız olup olmadığını seçin ve para biriminizde limiti girin. **Daily** bütçe, hâlâ öğrenirken daha fazla esneklik sağlar; böylece küçük miktarlarla başlayıp giderek ayarlayabilirsiniz. Reklam setinin başlangıç ve varsa bitiş tarihlerini belirleyin. Örneğin uygulamanızdaki bir promosyon teklifini tanıtmak istiyorsanız reklam setinin zaman dilimini teklifle uyumlu hâle getirmeniz kritik önem taşır. 7. **Audience controls** bölümünde kitle ayarlarını yapın: - **Location**: Konumlar, ihtiyacınıza göre geniş veya dar olabilir. Reklamlarınızdaki bölge özelliklerine göre çalışmak için reklam setindeki **Locations** alanını sınırlayabilirsiniz. - **Minimum age**: Reklamınızı görecek kullanıcıların minimum yaşını seçin. Bazı reklamlar için bu yasal olarak zorunlu olabilir. Minimum yaşı küresel olarak 18'in, Tayland'da ise 20'nin altına ayarlayamazsınız. - **Language**: **Language** seçeneğini yalnızca seçilen ülkelerde en yaygın dil değilse ayarlayın. Örneğin Amerika Birleşik Devletleri'nde **English** seçmenize gerek yoktur; ancak orada yaşayan İspanyolca konuşan kişileri hedefliyorsanız **Spanish** seçmek isteyebilirsiniz. 8. Meta varsayılan olarak reklamınızın ilgili olacağı küçük kullanıcı gruplarını otomatik bulur. Ancak bir kitle önerisi eklerseniz Meta'yı, yanıt verme ihtimali yüksek olduğunu düşündüğünüz kişilere yönlendirebilirsiniz. **Advantage+ audience** bölümünde şunları ayarlayabilirsiniz: - **Age**: Farklı yaş gruplarının özelliklerini daha iyi yakalayabilmek için belirli bir yaş aralığı hedefleyin. - **Gender**: Reklamınızı tüm kullanıcılara gösterin veya cinsiyete göre hedefleyin. - **Detailed targeting**: Bu ayar, reklamınızın ve/veya uygulamanızın kitlesini en ayrıntılı biçimde kontrol etmenizi sağlar. Burada **Demographics**, **Interests** veya **Behaviors** temelinde gruplar oluşturabilirsiniz. Uygulamanızın ne yaptığına bağlı olarak, örneğin belirli mesleklere, belirli müzik gruplarının hayranlarına, yeni doğan bebek ebeveynlerine ya da sık online alışveriş yapanlara odaklanabilirsiniz. :::note **Detailed targeting** ayarları **Or** operatörüyle uygulanır. Koşulları **And** operatörüyle uygulamak istiyorsanız **Define further** seçeneğine tıklayın ve yeni koşullar ekleyin. ::: 9. **Placements** bölümünde reklamınızın nerede görüneceğini seçebilirsiniz. Varsayılan olarak **Advantage+** ayarı seçilidir; bu, Meta'nın reklam setinizin bütçesini en iyi performans göstereceği yerlere göre birden fazla yerleşime dağıtmasını sağlar. Reklamınızı nereye yerleştireceğinizden emin değilseniz bu seçeneği kullanmanızı öneririz. Yerleşimleri manuel olarak seçmek istiyorsanız **Manual placements** seçeneğini belirleyip özelleştirin. Daha fazla bilgi için [buraya](https://www.facebook.com/business/help/965529646866485) bakın. 10. **Önerilen**: Cihaza göre hedefleme, harcamalarınızı optimize etmenize yardımcı olur. **Placements** bölümünde **Show more settings** seçeneğine tıklayın. **Devices and operating system** alt bölümünde kitlenize dahil edilecek cihazları, işletim sistemlerini ve işletim sistemi sürümlerini seçin. Bu, reklamlarınızın yalnızca ilgili kullanıcılara gösterilmesini sağlar. Örneğin masaüstü kullanıcıları reklamınızı görmez ve uygulamanızın desteklemediği eski işletim sistemi sürümlerine sahip kullanıcılar kapsam dışında kalır. 11. Hazır olduğunuzda devam etmek için **Next** seçeneğine tıklayın. ## Adım 5. Reklam Oluşturun \{#step-5-create-ads\} Meta Ads Manager'da reklam oluşturmak için: 1. **Ad name** alanına reklamınıza bir isim verin. 2. **Identity** bölümünde, reklamların yayınlanacağı Facebook sayfasını seçin. Uygulamanıza özel bir Instagram hesabınız varsa ve bunu [1. Adım'da](#step-1-create-meta-ads-manager-account) Meta Business Suite'e bağladıysanız, **Instagram account** açılır menüsünden onu seçin. Aksi takdirde **Use Facebook page** seçeneğini belirleyin; böylece Instagram reklamları Facebook sayfanız üzerinden yayınlanır. 3. **Ad setup** bölümünde, reklamınızı nasıl yayınlamak istediğinizi seçin. Uygulama reklamcılığında **Create ad** seçeneğini öneriyoruz; bu sayede gönderiniz kullanıcıları Facebook sayfası yerine uygulamanıza yönlendirir. **Format** alanında, sahip olduğunuz kreatif sayısına ve gösterim şekline göre bir seçenek belirleyin. 4. **Destination** bölümünde, **Main destination** olarak **Website** seçili kalsın. **Website URL** alanına `https://api-ua.adapty.io/api/v1/attribution/click` adresini yapıştırın. [Adapty Attribution](adapty-user-acquisition) bölümünde [bir web kampanyası oluşturun](ua-facebook) ve **Click link** içeriğini `https://api-ua.adapty.io/api/v1/attribution/click` adresinin sonuna ekleyerek **Tracking** bölümündeki **URL parameters** alanına yapıştırın. 5. **Ad creative** bölümünde **Set up creative** düğmesine tıklayın ve **Image ad** ya da **Video ad** seçeneğini belirleyin. Bu, medya dosyalarını yüklemenizi, kırpmanızı ve metin eklemenizi sağlayan yeni bir pencere açar. 6. Reklam metinlerinizin otomatik olarak çevrilmesini istiyorsanız **Languages** bölümünde **Add languages** seçeneğine tıklayın. Ardından birincil bir dil ekleyin; bu dil, kreatifinizden metinleri otomatik olarak alacaktır. Daha sonra otomatik çeviri için hedef dilleri ekleyin. 7. Hazır olduğunuzda reklamınızı yayınlamak için **Publish** düğmesine tıklayın. ## Sıradaki adımlar \{#whats-next\} Reklamınızı etkinleştirmek için, daha önce yapmadıysanız bir ödeme yöntemi eklemeniz gerekecek. Ardından, [kampanyanın uygulama gelirinizi nasıl etkilediğini Adapty Attribution kontrol panelinde inceleyebilirsiniz](adapty-user-acquisition). Adapty Attribution'ı henüz kullanmıyor musunuz? Reklam kampanyalarınızı takip etmenize ve optimize etmenize nasıl yardımcı olabileceğini öğrenmek için [bizimle bir görüşme ayarlayın](https://calendly.com/tnurutdinov-adapty/30min). --- # File: tiktok-create-campaign --- --- title: "TikTok for Business'ta uygulamanızı tanıtın" --- Bu adım adım kılavuzda, TikTok for Business'ta uygulamanız için nasıl reklam oluşturup ayarlayacağınızı öğreneceksiniz; böylece reklamlarınızı kolayca optimize edebilir ve performanslarını takip edebilirsiniz. ## Adım 1. İşletme bilgilerinizi ekleyin \{#step-1-add-business-info\} TikTok for Business'ı yeni kullanmaya başlıyorsanız önce işletme bilgilerinizi eklemeniz gerekir: 1. [https://ads.tiktok.com](https://ads.tiktok.com/business/) adresine gidin ve **Get started** butonuna tıklayın. 2. E-posta adresinizle veya TikTok hesabınızla kaydolun. 3. İşletme bilgilerinizi girin ve ekrandaki yönergeleri takip edin. İşletme hesabınız onaylandıktan sonra ilk kampanyanızı oluşturma adımına yönlendirileceksiniz. ## Adım 2. Piksel oluşturun \{#step-2-create-a-pixel\} Kampanya verilerinizi gelirle ilişkilendirmek ve daha iyi sonuçlar elde etmek için bir TikTok pikseline ihtiyacınız olacak: 1. [**Events Manager**](https://ads.tiktok.com/i18n/events_manager/home) sayfasına gidin. **Connect data source** seçeneğine tıklayın. 2. Veri kaynağı türü olarak **Web**'i seçin. 3. **Add your website** penceresinde **Skip** seçeneğine tıklayın. 4. **Manual setup** seçeneğini belirleyin ve **Next** düğmesine tıklayın. 5. **TikTok pixel + Events API** seçeneğini belirleyin ve **Next** düğmesine tıklayın. 6. Piksele bir ad verin ve **Create** düğmesine tıklayın. 7. [Adapty Attribution](adapty-user-acquisition) için pikselin tam kurulumunu tamamlamanız gerekmez. Kurulum penceresini kapatabilirsiniz; pikseliniz listede görünecektir. 8. Bu pikseli kampanyalarda kullanılabilir hale getirmek için [Adapty Attribution](adapty-user-acquisition) üzerinden piksele bir test etkinliği göndermeniz gerekir: 1. [Yeni bir TikTok kampanyası oluşturun](ua-tiktok). 2. Platforma özgü bir bölümü genişletin — örneğin iOS. 3. Açılır listeden bir piksel seçin. 4. **Send test event** düğmesine tıklayın. 5. Açılır listeden reklamda optimizasyon için kullanacağınız etkinliği seçin. 6. TikTok for Business'ta pikselinizi açın ve **Test events** sekmesine geçin. `test_event_code` değerini kopyalayın. 7. Kopyaladığınız değeri Adapty'deki **Test event code** alanına yapıştırın ve **Send** düğmesine tıklayın. 9. Test etkinliği birkaç dakika içinde TikTok'ta görünecektir. Piksel ayrıntılarında göründüğünde TikTok Ads Manager'da kampanya kurulumuna devam edebilirsiniz. ## Adım 3. Kampanya amacını seçin \{#step-3-select-the-campaign-objective\} :::important Bu kılavuz, TikTok Ads Manager'daki Hızlı kurulum görünümünü kullanmaktadır. Önerilen birkaç ayar yalnızca Tam görünümde yer almaktadır; bunlar ilgili adımlarda belirtilmiştir. ::: Ads Manager'daki [reklam oluşturma sayfasına](https://ads.tiktok.com/i18n/nb_creation/create/objectives) gidin. İlk ekranda reklam amacınızı seçin ve **Continue**'ya tıklayın. **Sales > Website conversion** seçeneğini belirleyin. ## Adım 4. Kampanya bilgilerini doldurun \{#step-4-fill-in-the-campaign-info\} Sonraki adımda kampanya bilgilerini doldurun: 1. **Campaign name** alanına kampanyanızın adını girin. 2. **Optimization goal** alanında **Conversion** seçeneğini belirleyin. 3. Açılır menüden aktif pikselinizi seçin ve bir **Optimization event** belirleyin. Yalnızca aktif olayların seçilebildiğini unutmayın. İhtiyacınız olan olay mevcut değilse, [Adım 2](#step-2-create-a-pixel) bölümündeki talimatları izleyerek bir test olayı gönderin. 4. Reklamınız TikTok akışında ve aramada görüntülenecektir. Ek kurulum için **Advanced settings** seçeneğine tıklayın. **Placements** bölümünde yerleşim ayarlarını yapılandırın: - **User comment**: Reklamınızın yorum bölümünde de görünmesini istiyorsanız seçin. TikTok, reklamlarınızın daha fazla gösterim elde etmesine yardımcı olmak için kullanıcı yorumlarını açık bırakmanızı önerir. - **Allow video download**: İzleyicilerin reklamınızı indirmesine izin verin. - **Allow video sharing**: İzleyicilerin reklamınızı paylaşmasına izin verin. 5. **Continue** seçeneğine tıklayın. ## 5. Adım. Reklam içeriği ekle \{#step-5-add-ad-content\} Şimdi görselleri ve hedef URL'yi ayarlama zamanı: 1. **TikTok account** alanında, gönderi için kullanılacak hesabı seçin. 2. [Adapty Attribution](adapty-user-acquisition) bölümünde [bir web kampanyası oluşturun](ua-tiktok) ve **Click link** değerini **Destination URL** alanına yapıştırın. 3. **Creatives** bölümünde **+ Videos and images** seçeneğine tıklayın. 4. TikTok gönderilerinizi reklam materyali olarak kullanmak istiyorsanız, bunları **TikTok post tab** sekmesinde seçin. Aksi takdirde **Creative library** sekmesine geçip **Upload** seçeneğine tıklayın. Oraya yüklediğiniz dosyalara daha sonra bu sekmeden erişebilir ve diğer kampanyalarda yeniden kullanabilirsiniz. 5. Reklam materyallerini TikTok formatına uygun şekilde kırpın ve tek reklam mı yoksa bir carousel mı olarak kullanılacağını seçin. 6. Yüklenen reklam materyalini genişletin ve **No music selected** seçeneğinin yanındaki **+** simgesine tıklayın. Oraya kendi mp3 dosyalarınızı yükleyebilirsiniz. Müzik eklenmesi zorunludur. 7. **Add text** alanına, açıklama olarak kullanılacak metni girin. 8. Bu reklamı TikTok hesabınıza gönderi olarak paylaşmak istiyorsanız **Place the ads on this TikTok account as a post** seçeneğini işaretleyin. 9. **Call to action** alanında, reklamınızla alakalı harekete geçirici mesajları seçin ya da kaldırın. Bunlar TikTok tarafından reklamınıza otomatik olarak eklenir. 10. **Continue** seçeneğine tıklayın. ## Adım 6. Hedefleme ve bütçeyi yapılandırın \{#step-6-configure-targeting-and-budget\} Son olarak, reklamınızı kimin göreceğini ve ne kadar ödemeyi planladığınızı ayarlayın: 1. **Hedefleme** bölümünde **Otomatik** veya **Özel** seçeneğini belirleyin. Kitlenizi henüz iyi tanımıyorsanız **Otomatik** seçeneği en kolay yoldur. Ancak **Özel** seçeneğini tercih ederseniz, reklamınıza daha olası yanıt verecek kullanıcı gruplarını belirleyerek harcamalarınızı optimize edebilirsiniz. 2. **Özel** seçeneğini seçtiyseniz şunları yapılandırın: - **Konum**: Varsayılan konum, reklam hesabınızın konumudur. Birden fazla hedefleme ülkesi veya bölgesi seçerseniz reklam inceleme sonuçları her konum için ayrı ayrı döndürülür. Gerçek reklam yayını da farklı placement'ların desteklenen konumlarına göre değişiklik gösterebilir. - **Diller**: Varsayılan olarak tüm diller seçilidir. Seçtiğiniz konumda en sık kullanılan dile göre hedefleme dilini belirleyin. - **Cinsiyet**: Varsayılan olarak tüm cinsiyetler seçilidir. :::tip Tam moda geçerseniz, **Hedefleme** altında ek bir **Cihaz** bölümü göreceksiniz. Burada kitlenizi cihaz türüne, işletim sistemine ve işletim sistemi sürümüne göre sınırlayabilirsiniz; bu özellikle uygulamanızın minimum bir sürüm gerektirdiği durumlarda işe yarar. ::: 3. **Bütçe** bölümünde önerilen seçeneklerden birini belirleyin ya da **Özel** seçeneğini seçin. 4. **Özel** seçeneğini seçtiyseniz **Günlük** mi yoksa **Ömür Boyu** bütçeye mi ihtiyaç duyduğunuzu belirleyip para biriminizde limiti girin. **Günlük** bütçe, henüz öğrenme aşamasındayken daha fazla esneklik sağlar; böylece küçük miktarlarla başlayıp zamanla ayarlamalar yapabilirsiniz. 5. **Zamanlama** bölümünde **En az 7 gün devam et** veya **Özel** seçeneğini belirleyin. Reklamınızın zamanlamaya duyarlı olması durumunda durdurmayı gerektiren anı kaçırmamak için **Özel** zamanlama ayarlamanızı öneririz. 6. **Özel** seçeneğini seçtiyseniz reklamlar için başlangıç ya da başlangıç ve bitiş zamanını ayarlayın. Hesap saat diliminizin kullanılacağını unutmayın. 7. **Yayımla**'ya tıklayın. Tamamladığınızda, bir reklam grubu içeren yeni bir kampanya oluşturulur. Döngüsel (carousel) yapılandırdıysanız reklam grubu tek bir reklam içerir; reklamları ayrı ayrı eklediyseniz birden fazla reklam içerir. ## Adım 7. Ödeme bilgilerini girin \{#step-7-enter-payment-details\} Reklamı yayına almak için hedefleme ve reklam bütçesini yapılandırdıktan sonra ödeme bilgilerinizi girin. Bundan sonra her şey hazır! ## Sıradaki adımlar \{#whats-next\} Artık [kampanyanın uygulama gelirinizi nasıl etkilediğini Adapty User Acquisition kontrol panelinde inceleyebilirsiniz](adapty-user-acquisition). Adapty User Acquisition'ı henüz kullanmıyor musunuz? Reklam kampanyalarınızı nasıl takip edip optimize edebileceğinizi öğrenmek için [bizimle bir görüşme ayarlayın](https://calendly.com/tnurutdinov-adapty/30min). --- # File: getting-started-with-server-side-api --- --- title: "Sunucu Taraflı API" description: "Adapty'nin abonelik yönetimi için sunucu taraflı API'siyle başlayın." --- :::tip Bir AI kodlama ajanı mı kullanıyorsunuz? Tek sayfada uçtan uca bir tarif için [Backend'inizden abonelik erişimini kontrol etme ve verme](server-side-api-with-ai) konusuna bakın. ::: API ile şunları yapabilirsiniz: 1. Kullanıcının abonelik durumunu kontrol etme. 2. Kullanıcının aboneliğini bir access level ile etkinleştirme. 3. Kullanıcı özelliklerini alma. 4. Kullanıcı özelliklerini ayarlama. 5. Paywall yapılandırmalarını alma ve güncelleme. <img src="/assets/shared/img/server.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note Abonelik olaylarını takip etmek için Adapty'deki [Webhook](webhook) entegrasyonunu kullanın ya da mevcut servisinizle doğrudan entegre edin. ::: ::: ## Durum 1: Web ve mobil arasında aboneleri senkronize etme \{#case-1-sync-subscribers-between-web-and-mobile\} Stripe, ChargeBee veya başka web ödeme sağlayıcıları kullanıyorsanız, abonelerinizi kolayca senkronize edebilirsiniz. İşte nasıl yapacağınız: 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. API üzerinden [abonelik durumunu kontrol edin](api-adapty/operations/getProfile). 3. Kullanıcı ücretsiz planda ise web sitenizde bir paywall gösterin. 4. Başarılı bir ödemenin ardından [abonelik durumunu](api-adapty/operations/setTransaction) API üzerinden Adapty'de güncelleyin. 5. Aboneleriniz mobil uygulamanızla otomatik olarak senkronize olmaya devam eder. ## 2. Durum: Abonelik ver \{#case-2-grant-a-subscription\} :::note Güvenlik nedeniyle, mobil SDK aracılığıyla abonelik veremezsiniz. ::: Google Play ve App Store dışında kendi online mağazanız, Amazon Appstore, Microsoft Store veya başka bir platform üzerinden satış yapıyorsanız, erişim sağlamak ve işlemi analitikte takip etmek için bu işlemleri Adapty ile senkronize etmeniz gerekir. 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. [Adapty Kontrol Paneli'nde ürünleriniz için özel bir mağaza kurun](custom-store). 3. İşlemi [Set transaction](api-adapty/operations/setTransaction) API isteğini kullanarak Adapty ile senkronize edin. ## Durum 3: Access level tanımlama \{#case-3-grant-an-access-level\} Diyelim ki 7 günlük ücretsiz deneme sunan bir promosyon yürütüyorsunuz ve deneyimin platformlar arasında tutarlı olmasını istiyorsunuz. Bunu mobil uygulama ile senkronize etmek için: 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users) ve [Unity](unity-identifying-users)</InlineTooltip>. 2. 7 gün boyunca [premium erişim vermek](api-adapty/operations/grantAccessLevel) için API'yi kullanın. 7 gün sonra abone olmayan kullanıcılar ücretsiz katmana düşürülecektir. ## Durum 4: Kullanıcı özelliklerini ve özel nitelikleri senkronize etme \{#case-4-sync-users-properties-and-custom-attributes\} Kullanıcılarınız için özel nitelikler varsa—örneğin bir dil öğrenme uygulamasında öğrenilen kelime sayısı—bunları da senkronize edebilirsiniz. 1. <InlineTooltip tooltip="Her kullanıcıya benzersiz bir ID atayın">[iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), and [Unity](unity-identifying-users)</InlineTooltip>. 2. API veya SDK aracılığıyla [niteliği güncelleyin](api-adapty/operations/updateProfile). Bu özel nitelikler, segment oluşturmak ve A/B testleri çalıştırmak için kullanılabilir. ## Durum 5: Paywall yapılandırmalarını yönetme \{#case-5-manage-paywall-configurations\} Uygulamanızı yeniden dağıtmadan paywall görünümünü ve davranışını dinamik olarak ayarlamak için [paywall'lardaki remote config'leri güncelleyebilirsiniz](api-adapty/operations/updatePaywall). --- **Sıradaki adımlar:** - [Sunucu tarafı API için yetkilendirme](ss-authorization) ile devam edin - İstekler: - [Profil al](api-adapty/operations/getProfile) - [Profil oluştur](api-adapty/operations/createProfile) - [Profil güncelle](api-adapty/operations/updateProfile) - [Profil sil](api-adapty/operations/deleteProfile) - [Access level ver](api-adapty/operations/grantAccessLevel) - [Access level iptal et](api-adapty/operations/revokeAccessLevel) - [İşlem ayarla](api-adapty/operations/setTransaction) - [Satın almayı doğrula, müşteriye access level sağla ve işlem geçmişini içe aktar](api-adapty/operations/validateStripePurchase) - [Entegrasyon tanımlayıcıları ekle](api-adapty/operations/setIntegrationIdentifiers) - [Paywall al](api-adapty/operations/getPaywall) - [Paywall'ları listele](api-adapty/operations/listPaywalls) - [Paywall güncelle](api-adapty/operations/updatePaywall) --- # File: onboardings --- --- title: "Onboardings" --- :::warning Kodsuz onboarding oluşturucu tam işlevseldir, ancak Adapty artık bu araç için yeni özellik eklemeyecek veya güncelleme yayınlamayacaktır. Yeni projeler için, cihazda yerel olarak render edilen tek ekranlı paywall'lar ve çok ekranlı onboarding flow'ları tasarlamak amacıyla kullanabileceğiniz görsel kodsuz editör olan [Adapty Flow Builder](adapty-flow-builder)'ı değerlendirmenizi öneririz: - **Her türlü flow**: Tek ekranlı paywall'lar, paywall içeren çok adımlı onboarding'ler ve bunların arasındaki her şeyi oluşturun. - **Yerel render**: Flow'lar, web görünümleri olmadan Adapty SDK aracılığıyla render edilir. - **Yeniden dağıtmadan güncelleyin**: Metin, tasarım veya mantığı istediğiniz zaman değiştirin; güncellemeler uygulama sürümü çıkarmadan kullanıcılara ulaşır. ::: Adapty'nin onboarding'leri, teknik bilgisi olmayan ekiplerin kod yazmadan onboarding flow'ları oluşturmasına olanak tanır. Kodsuz oluşturucu, kullanıcıları uygulamanızla tanıştıran bir dizi ekran oluşturur. Ekranları etkileşimli sorular ve değişkenlerle kişiselleştirebilir, ardından en iyi performans gösteren flow'u bulmak için A/B testleri çalıştırabilirsiniz. Onboarding'ler; Adapty SDK v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity) veya v3.15.0+ (Kotlin Multiplatform, Capacitor) kullanan uygulamalar için kullanılabilir. ## Nasıl çalışır \{#how-it-works\} 1. [Kodsuz editörde bir onboarding tasarlayın.](design-onboarding) 2. [Onboarding için bir placement oluşturun.](create-onboarding#step-2-create-a-placement-for-your-onboarding) 3. Adapty SDK'yı kullanarak onboarding'i projenizle entegre edin: - [iOS](ios-onboardings) - [Android](android-onboardings) - [React Native](react-native-onboardings) - [Flutter](flutter-onboardings) - [Unity](unity-onboardings) - [Kotlin Multiplatform](kmp-onboardings) - [Capacitor](capacitor-onboardings) 4. Onboarding'i test edin ve kullanıcılarınız için yayına alın. --- # File: create-onboarding --- --- title: "Onboarding oluşturma" --- [Onboardings](onboardings), yeni kullanıcıları mobil uygulamanızın değeriyle, özellikleriyle ve kullanım ipuçlarıyla tanıştırır. ## Adım 1. Onboarding oluşturma \{#step-1-create-an-onboarding\} Adapty kontrol panelinde yeni bir onboarding oluşturmak için: 1. Adapty ana menüsünden **Onboardings** sayfasına gidin. Bu sayfa, oluşturduğunuz tüm onboarding'lere ve bunların metriklerine genel bir bakış sunar. **Create onboarding** düğmesine tıklayın. <img src="/assets/shared/img/create-onboarding1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Onboarding'iniz için açıklayıcı bir isim girin ve **Proceed to build onboarding** düğmesine tıklayın. <img src="/assets/shared/img/create-onboarding2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Onboarding oluşturucuya yönlendirileceksiniz. Onboarding'in verileri nasıl topladığını ve değişkenler ile quizler aracılığıyla nasıl kişiselleştirilebileceğini anlamak için inceleyebileceğiniz varsayılan bir demo şablon içerir. İhtiyacınız olmayan ekranları kaldırabilir ve [kendi onboarding deneyiminizi tasarlayabilirsiniz](design-onboarding). <img src="/assets/shared/img/create-onboarding3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Hazır olduğunuzda sağ üstteki **Preview** düğmesine tıklayın. Her şeyin beklendiği gibi çalıştığından emin olmak için onboarding akışını kendiniz tamamlayın. <img src="/assets/shared/img/create-onboarding4.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Her şey düzgün çalışıyorsa sağ üstteki **Publish** düğmesine tıklayın. Adapty'ye geri dönmeden önce yayınlanmasını bekleyin; aksi takdirde ilerlemeniz kaybolur. :::danger **Publish** düğmesine tıklamazsanız SDK, oluşturduğunuz onboarding'i alamaz. ::: <img src="/assets/shared/img/create-onboarding5.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Onboarding'iniz yayınlandıktan sonra **Back to Adapty** düğmesine tıklayın. Onboarding'iniz oluşturuldu; kullanmaya başlamak için bir placement'a ekleyebilirsiniz. ## Adım 2. Onboarding için placement oluşturma \{#step-2-create-a-placement-for-your-onboarding\} 1. Ana menüden **Placements** sayfasına gidin ve **Onboardings** sekmesine geçin. **Create placement** düğmesine tıklayın. <img src="/assets/shared/img/create-onboarding6.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Placement adını ve kimliğini girin. Ardından **Run onboarding** düğmesine tıklayın ve tüm kullanıcılara gösterilecek onboarding'i seçin. 3. Belirli bir kullanıcı grubu için ayrı bir onboarding hazırladıysanız [daha fazla kitle ekleyin](audience) ve onlar için farklı bir onboarding seçin. ## Adım 3. Onboarding'i uygulamanıza entegre etme \{#step-3-integrate-the-onboarding-into-your-app\} :::important Onboardings; Adapty SDK v3.8.0 ve üzeri (iOS, Android, React Native, Flutter), v3.14.0 ve üzeri (Unity) veya v3.15.0 ve üzeri (Kotlin Multiplatform, Capacitor) kullanan uygulamalar için kullanılabilir. ::: Onboarding'leri uygulamanızda görüntülemeye başlamak için Adapty SDK ile entegre edin: - [iOS](ios-onboardings) - [Android](android-onboardings) - [React Native](react-native-onboardings) - [Flutter](flutter-onboardings) - [Unity](unity-onboardings) - [Kotlin Multiplatform](kmp-onboardings) - [Capacitor](capacitor-onboardings) Hangi onboarding'in daha iyi çalıştığını anlamak için [A/B testleri](ab-tests) de çalıştırabilirsiniz. --- # File: design-onboarding --- --- title: "Onboarding tasarımı" description: "Anlamlı onboardinglar oluşturun." --- Kodsuz mobil uygulama onboarding builder'ı, kullanıcılarınıza en iyi onboarding deneyimini sunmanıza yardımcı olacak güçlü ve özelleştirilebilir bir araçtır. Harika sonuçlar elde etmek için geliştirici ya da tasarımcı olmanıza gerek yok. ## Onboarding ekranları \{#onboarding-screens\} Onboarding flow'u, eklediğiniz ve tasarladığınız birkaç ekrandan oluşur. Kullanıcılar, ekranlar arasında gezinmek için butona dokunur. :::tip Bazı kullanıcılarınızın biraz farklı bir flow'a ihtiyacı varsa (örneğin bir fitness uygulamasında, kullanıcının cinsiyetine göre farklı 'hedef' görselleri göstermek isteyebilirsiniz), ayrı onboarding'ler oluşturmanıza gerek yok. Bunun yerine, bazı ekranları varsayılan olarak gizli yapabilir ve yalnızca belirli senaryolarda gösterilecek şekilde ayarlayabilirsiniz. ::: ## Onboarding öğeleri \{#onboarding-elements\} Onboarding öğeleri sol tarafta, gösterildikleri sırayla listelenir. Yeni bir öğe eklemek için sağ üstteki **Add** butonuna tıklayın. Ekleyebileceğiniz öğe grupları şunlardır: - **Containers**: Container'lar esnek bir düzen oluşturmanıza olanak tanır. Örneğin iki sütunlu bir metin eklemek istiyorsanız **Columns** ekleyip ardından sol paneldeki **Columns** içine iki metin bloğu sürüklemeniz gerekir. Carousel eklemek için ise içindeki **Media** öğelerine resim eklemeniz gerekir. - **Typography**: Önceden biçimlendirilmiş metin blokları ekleyin ve görünümlerini ihtiyacınıza göre düzenleyin. - **Media & Display**: Resim ve videolara ek olarak, uygulamanızın değerini gösteren ve kullanıcıları teşvik eden animasyonlu grafikler ekleyebilirsiniz. **Desteklenen video formatları** MP4 ve WebM'dir. **Maksimum medya dosyası boyutu** 15 MB'tır. Desteklenmeyen animasyonlu bir öğe eklemek istiyorsanız (örneğin Lottie), bunu bir videoya dönüştürebilir (örneğin [bu araçla](https://www.lottielab.com/lottie/lottie-to-video)) ve video olarak yerleştirebilirsiniz. - **Quiz**: Onboarding deneyimini kişiselleştirmek ve kullanıcılarınızı daha iyi tanımak için metin ve resim seçenekli kısa anketler oluşturun. - **Inputs**: Kullanıcılarınızın verilerini toplayın. - **Buttons**: Butonlar, kullanıcıların ekranlar arasında geçiş yapmasını, onboarding'i kapatmasını veya paywalla geçmesini sağlar. Kullanıcıların dikkatini çekmek ve kurulumu satın almaya dönüştürmek için parlak veya hareketli butonlar da ekleyebilirsiniz. - **Loaders**: Animasyonlu yükleyiciler, süreç boyunca kullanıcıların ilgisini canlı tutar. - **User engagement**: Referanslar, kullanıcı e-posta listeleri ve geri sayımlar ekleyin. :::note **Media & Display** grubu kapsamında, sağlanan özelleştirme seçenekleri yetmediğinde özel HTML kodu da ekleyebilirsiniz. Ancak özel HTML öğeleri ne önceden yüklenir ne de önbelleğe alınır; bu nedenle **Raw HTML**'i yalnızca küçük ve hafif öğeler için kullanmanız önerilir. ::: <img src="/assets/shared/img/design-onboarding4.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Öğe kimliği ve eylem kimliği \{#element-id-and-action-id\} Bir butonu özel eylemler için kullanmak istiyorsanız ona bir **action ID** atayın ve ardından kaynak kodunuzda bu kimliği kullanın. Eylem kimlikleri, aynı eylem kimliğine sahip farklı butonları aynı şekilde ele almanıza olanak tanır. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Belirli bir alandaki kullanıcı girişini işlemek istiyorsanız (örneğin yaş veya e-posta kaydetmek), alana bir **element ID** atayın ve ardından soruları yanıtlarla ilişkilendirmek için kaynak kodunuzda bu kimliği kullanın. Öğe kimlikleri onboarding'inizde yalnızca bir kez kullanılabilir. <img src="/assets/shared/img/design-onboarding5.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Özelleştirme seçenekleri \{#customization-options\} Builder'da şu özelleştirme seçenekleri mevcuttur: - **Styles** sekmesi: Öğenin görünümünü ayarlayın. <img src="/assets/shared/img/design-onboarding1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Element** sekmesi: Görünebilirlik, buton basma eylemleri veya öğenin görünümüyle ilgisi olmayan diğer özellikler gibi öğe niteliklerini ayarlayın. <img src="/assets/shared/img/design-onboarding2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Screen** sekmesi: Başlık veya ekran sayacı gösterimi gibi genel ekran yapılandırmasını ayarlayın. <img src="/assets/shared/img/design-onboarding3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Ekranları ve öğeleri kopyalama \{#copy-screens-and-elements\} Bir onboarding oluşturdunuz ve bazı bölümlerini yeniden kullanmak ya da küçük değişiklikler yapıp A/B testleri çalıştırmak istiyorsanız, bir onboarding'den diğerine bir veya birden fazla ekran kopyalayabilirsiniz. Ekranları kopyalamak için onboarding builder'ı açın ve şunlardan birini yapın: - Tek bir ekrana sağ tıklayın ve **Copy** seçeneğini seçin - İstediğiniz ekranı seçin ve `Ctrl+C` (Windows) veya `⌘+C` (Mac) tuşlarına basın Aynı onboarding içinde veya farklı onboardingler arasında tek tek öğeleri ya da metin bloklarını da kopyalayabilirsiniz. ## Web-to-app hunilerinden ekran kopyalama \{#copy-screens-from-web-to-app-funnels\} [FunnelFox](https://funnelfox.com/)'ta oluşturulan web-to-app hunilerini kullanıyorsanız ve huni ekranlarını onboardinglerde kullanmak istiyorsanız, huni builder'ında ekranları kopyalayıp onboarding builder'ına yapıştırarak bunu hızlıca yapabilirsiniz: 1. FunnelFox huni builder'ında bir ekrana sağ tıklayın ve **Copy** seçeneğini seçin ya da ekranı seçin ve `Ctrl+C`/`⌘+C` tuşlarına basın. 2. Onboarding builder'ını açın. 3. Kopyalanan ekranı eklemek istediğiniz yere sağ tıklayın ve **Paste** seçeneğini seçin ya da seçili durumdayken `Ctrl+V`/`⌘+V` tuşlarına basın. Kopyalanan ekran, seçili ekranın altına eklenir. <img src="/assets/shared/img/funnel-to-onboarding.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: adapty-paywall-builder --- --- title: "Adapty Paywall Builder (Legacy)" description: "Görsel no-code builder ile paywall'lar ve onboarding flow'ları oluşturun." --- :::warning Paywall Builder tamamen işlevseldir, ancak Adapty artık bu ürüne yeni özellik eklemiyor veya güncelleme çıkarmıyor. Yeni projeler için cihazda yerel olarak çalışan tek ekranlı paywall'lar ve çok ekranlı onboarding flow'ları tasarlamak amacıyla kullanabileceğiniz görsel, kodsuz bir editör olan [Adapty Flow Builder](adapty-flow-builder)'ı değerlendirmenizi öneririz: - **Her tür flow**: Tek ekranlı paywall'lar, paywall içeren çok adımlı onboarding'ler ve bunlar arasındaki her şeyi oluşturun. - **Native rendering**: Flow'lar, web view kullanmadan Adapty SDK üzerinden render edilir. - **Yeniden dağıtmadan güncelleme**: Metin, tasarım veya mantığı istediğiniz zaman değiştirin; güncellemeler uygulama sürümü çıkarmadan kullanıcılara ulaşır. ::: Adapty **Paywall Builder**, özel paywalllar tasarlamak için görsel bir no-code araçtır. Bir şablondan başlayabilir, düzeni özelleştirebilir ve carousel, kart, ürün listesi ile footer gibi öğeler ekleyebilirsiniz. Builder ayrıca özel fontları, ürün etiketlerini ve yerelleştirmeyi de destekler. Paywall Builder, Adapty SDK v3.0 veya sonrasını gerektirir. Paywallınızı tasarladıktan sonra [bir placement'a ekleyin](add-audience-paywall-ab-test) ve uygulamanızda gösterin: - [iOS](ios-quickstart-paywalls) - [Android](android-quickstart-paywalls) - [React Native](react-native-quickstart-paywalls) - [Flutter](flutter-quickstart-paywalls) - [Unity](unity-quickstart-paywalls) - [Capacitor](capacitor-quickstart-paywalls) - [Kotlin Multiplatform](kmp-quickstart-paywalls) --- # File: flutterflow --- --- title: "FlutterFlow için Adapty Eklentisi" description: "Gelişmiş abonelik yönetimi için FlutterFlow'u Adapty ile entegre edin." --- Adapty, mobil uygulamaların büyümesine yardımcı olmak için tasarlanmış çok yönlü bir platformdur. Yeni başlıyor olsanız da binlerce kullanıcınız olsa da Adapty; uygulama içi satın almaları entegre etmek için harcayacağınız zamanı aylarca kısaltır ve paywall yönetimiyle abonelik gelirinizi iki katına çıkarmanızı sağlar. FlutterFlow için Adapty eklentisi, tek satır kod yazmadan Adapty'nin tüm özelliklerinden yararlanmanızı sağlar. FlutterFlow'da paywall sayfaları tasarlayabilir, satın alma işlemlerini etkinleştirebilir; ardından hangi ürünlerin görüntüleneceğini, belirli kullanıcı gruplarını hedeflemeyi veya A/B testini uzaktan yönetebilirsiniz. Uygulamanızı yayınladıktan sonra ise kullanıcılarınızın satın almalarına ait ayrıntılı analizlere doğrudan kontrol panelimizden anında erişebilirsiniz. Paywallınızdaki ürünleri güncellemek mi istiyorsunuz? Son derece kolay! Adapty Kontrol Paneli'nde birkaç tıklamayla değişiklik yapın; kullanıcılarınız yeni ürünleri hemen görsün — yeni bir uygulama sürümü yayınlamanıza gerek yok! Adapty'nin sunduğu diğer özellikler: - **Abonelikler ve Uygulama İçi Satın Almalar**: Adapty, sunucu tarafında makbuz doğrulamasını sizin için yönetir ve kullanıcılarınızı web dahil tüm platformlarda senkronize eder. - **Paywall'lar için A/B Testi**: Abonelik ve tek seferlik tekliflerinizi optimize etmek amacıyla farklı fiyatları, süreleri, deneme dönemlerini ve görsel öğeleri test edin. - **Güçlü analizler**: Uygulamanızın gelir modelini daha iyi anlamak ve iyileştirmek için ayrıntılı metriklere erişin. - **Entegrasyonlar**: Adapty; Amplitude, AppsFlyer, Adjust, Branch, Mixpanel, Facebook Ads, AppMetrica, özel Webhook'lar ve daha fazlası gibi üçüncü taraf analiz araçlarıyla sorunsuz biçimde entegre olur. --- # File: ff-getting-started --- --- title: "Başlarken" description: "Abonelik akışlarını kişiselleştirmek için Adapty Feature Flags'e başlayın." --- Adapty ile mobil uygulama kullanıcılarınızın yolculuğunun farklı noktalarında (Onboarding, Ayarlar vb.) paywall'lar oluşturabilir ve A/B testleri çalıştırabilirsiniz. Bu noktalara [Placement](placements) denir. Uygulamanızdaki bir placement, aynı anda birden fazla paywall veya [A/B testi](ab-tests) yönetebilir; bunların her biri [Kitle](audience) olarak adlandırdığımız belirli bir kullanıcı grubu için hazırlanır. Üstelik yeni bir uygulama sürümü yayınlamadan, zaman içinde bir paywall'u başkasıyla değiştirerek denemeler yapabilirsiniz. Mobil uygulamaya sabit kodlanan tek şey placement ID'sidir. <img src="/assets/shared/img/audience.jpg" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty kütüphanesi, paywall'ınızı Adapty Kontrol Paneli'ndeki en güncel ürünlerle senkronize tutar. [Ürün verilerini çeker](ff-action-flow), [bunları paywall'ınızda gösterir](ff-add-variables-to-paywalls), [satın alma işlemlerini yönetir](ff-make-purchase) ve kullanıcının ücretli içeriğe erişip erişemeyeceğini belirlemek için [access level durumunu kontrol eder](ff-check-subscription-status). Başlamak için aşağıda gösterildiği gibi FlutterFlow projenize [Adapty kütüphanesini ekleyin](ff-getting-started#add-the-adapty-library-as-a-dependency) ve [başlatın](ff-getting-started#initiate-adapty-plugin). :::warning Başlamadan önce aşağıdaki kısıtlamalara dikkat edin: - FlutterFlow için Adapty kütüphanesi web uygulamalarını desteklemez. Web uygulamalarını bu kütüphaneyle derlemeyin. - FlutterFlow için Adapty kütüphanesi, Adapty paywall builder kullanılarak oluşturulan paywall'ları desteklemez. Adapty üzerinden satın alma işlemlerini etkinleştirmeden önce kendi paywall'ınızı FlutterFlow'da tasarlamanız gerekir. ::: ## Adapty kütüphanesini bağımlılık olarak ekleyin \{#add-the-adapty-library-as-a-dependency\} 1. [FlutterFlow Dashboard](https://app.flutterflow.io/dashboard)'unu açın, projenizi seçin ve sol menüden **Settings and Integrations**'a tıklayın. Sol taraftaki **Project setup** bölümünden **Project dependencies**'i seçin. <img src="/assets/shared/img/main_settings.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **FlutterFlow Libraries** bölümünde **Add Library**'e tıklayın ve `adapty-xtuel0` girin. **Add**'e tıklayın. 3. Şimdi SDK anahtarınızı kütüphaneyle ilişkilendirmeniz gerekiyor. Kütüphanenin yanındaki **View details**'e tıklayın. <img src="/assets/shared/img/ff_view_details.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty Kontrol Paneli'ndeki [**App Settings** -> **General** sekmesinden](https://app.adapty.io/settings/general) **Public SDK key**'i kopyalayın. <img src="/assets/shared/FF_img/adaptyapikey.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Anahtarı FlutterFlow'daki **AdaptyApiKey** alanına yapıştırın. <img src="/assets/shared/img/ff_apikey.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty FF kütüphanesi artık projenize bağımlılık olarak eklenecek. **Adapty** FF kütüphane penceresinde, projenize aktarılan tüm Adapty kaynaklarını bulabilirsiniz. ## Uygulama başlangıcında yeni aktivasyon eylemini çağırın \{#call-the-new-activation-action-at-application-launch\} 1. Sol menüden **Custom Code** bölümüne gidin ve `main.dart` dosyasını açın. <img src="/assets/shared/img/ff_dartmain.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **+** işaretine tıklayın ve `activate (Adapty)` seçeneğini belirleyin. <img src="/assets/shared/img/ff_activate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Save**'e tıklayın. ## Adapty eklentisini başlatın \{#initiate-adapty-plugin\} Adapty Kontrol Paneli'nin uygulamanızı tanıyabilmesi için FlutterFlow'da özel bir anahtar girmeniz gerekir. 1. FlutterFlow projenizde sol menüden **Settings and Integrations > Permissions** bölümüne gidin. 2. Açılan **Permissions** penceresinde **Add Permission** düğmesine tıklayın. 3. **iOS Permission Key** ve **Android Permission Key** alanlarının her ikisine de `AdaptyPublicSdkKey` yapıştırın. 4. **Permission Message** için, Adapty Kontrol Paneli'ndeki [**App Settings** -> **General** sekmesinden](https://app.adapty.io/settings/general) **Public SDK key**'i kopyalayın. Her uygulamanın kendine ait bir SDK anahtarı vardır; dolayısıyla birden fazla uygulamanız varsa doğru anahtarı aldığınızdan emin olun. <img src="/assets/shared/img/ff_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adımları tamamladıktan sonra FlutterFlow uygulamanızda paywall'ınızı çağırabilir ve üzerinden satın alma işlemlerini etkinleştirebilirsiniz. ## Sırada ne var? \{#whats-next\} 1. FlutterFlow'da Adapty paywall ürünlerini ve verilerini işlemek için [bir action flow oluşturun](ff-action-flow). 2. [Alınan verileri](ff-add-variables-to-paywalls) FlutterFlow'da tasarladığınız paywall'a eşleyin. 3. Tıklandığında Adapty üzerinden işlem gerçekleştirmek için paywall'ınızdaki [satın alma düğmesini ayarlayın](ff-make-purchase). 4. Son olarak, kullanıcıya ücretli içerik gösterilip gösterilmeyeceğini belirlemek için [abonelik durumu kontrollerini ekleyin](ff-check-subscription-status). --- # File: ff-action-flow --- --- title: "Adım 1. Paywall verilerini göstermek için akış oluşturun" description: "Kullanıcı abonelik deneyimlerini kişiselleştirmek için Adapty'de özellik bayrağı eylem akışlarını ayarlayın." --- :::important FlutterFlow eklentisini kullanırken Adapty Paywall Builder'da oluşturulmuş paywallları kullanamazsınız. FlutterFlow'da kendi paywall sayfanızı oluşturmanız ve bunu Adapty'ye bağlamanız gerekir. ::: Adapty kütüphanesini FlutterFlow projenize bağımlılık olarak ekledikten sonra, **Adapty paywall ve ürün verilerini alıp FlutterFlow'da tasarladığınız paywall'da görüntüleyen** akışı oluşturma zamanı geldi. Önce Adapty'den paywall verilerini almamız gerekiyor. Adapty paywallını isteyerek başlayacağız, ardından buna bağlı ürünleri alacağız ve son olarak verilerin başarıyla alınıp alınmadığını kontrol edeceğiz. Başarılıysa paywall sayfasında ürün başlığını ve fiyatını göstereceğiz. Aksi hâlde bir hata mesajı görüntüleyeceğiz. Devam etmeden önce aşağıdakileri yaptığınızdan emin olun: 1. Adapty Kontrol Paneli'nde [en az bir paywall oluşturup buna en az bir ürün eklemiş](create-paywall) olun. 2. Adapty Kontrol Paneli'nde [en az bir placement oluşturun](create-placement) ve [paywallınızı buna ekleyin](add-audience-paywall-ab-test). Hadi başlayalım! ## Adım 1.1. Adapty paywallını isteyin \{#step-11-request-adapty-paywall\} Belirtildiği gibi, FlutterFlow paywall'ınızda veri göstermek için önce bunu Adapty'den almamız gerekiyor. İlk adım, Adapty paywallının kendisini almaktır. İşte nasıl yapılacağı: 1. Paywall ekranınızı açın ve sağ bölmedeki **Actions** bölümüne geçin. Orada **Action Flow Editor**'ı açın. <img src="/assets/shared/img/ff_action_flow.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Select Action Trigger** penceresinde **On Page Load** seçeneğini seçin. <img src="/assets/shared/img/ff_action_trigger.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Add Action**'a tıklayın. Ardından `getPaywall` özel eylemini arayın ve seçin. <img src="/assets/shared/img/ff_getpaywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Set Actions Arguments** bölümünde, paywallı içeren Adapty Kontrol Paneli'nde [oluşturduğunuz placement'ın](create-placement) gerçek kimliğini girin. Bu örnekte `monthly`. Gerçek placement kimliğinizi kullandığınızdan emin olun! <img src="/assets/shared/img/ff_placementid.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Paywallınızı Adapty kontrol panelinde [yerelleştirdiyseniz](localizations-and-locale-codes), **locale** bağımsız değişkenini de ayarlayabilirsiniz. 6. **Action Output Variable Name** alanında yeni bir değişken oluşturun ve `getPaywallResult` olarak adlandırın. Bunu bir sonraki adımda Adapty paywallına başvurmak ve ürünlerini istemek için kullanacağız. <img src="/assets/shared/img/ff_getpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 1.2. Adapty paywall ürünlerini isteyin \{#step-12-request-adapty-paywall-products\} Harika! Adapty paywallını aldık. Şimdi bu paywalla ilişkili ürünleri alalım: 1. Oluşturulan eylemin altındaki **+** simgesine tıklayın ve **Add Action**'ı seçin. Bu eylem Adapty paywall ürünlerini alacak. Bunun için `getPaywallProducts` eylemini arayın ve seçin. 2. **Set Actions Arguments** bölümünde, daha önce oluşturulan `getPaywallResult` değişkenini seçin. <img src="/assets/shared/img/ff_getpaywallproduct.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Diğer alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: No further changes <img src="/assets/shared/img/ff_getpaywallresult2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm**'e tıklayın. 5. **Action Output Variable Name** alanında yeni bir değişken oluşturun ve `getPaywallProductsResult` olarak adlandırın. Bunu, FlutterFlow'da tasarladığınız paywallı Adapty paywall verileriyle eşleştirmek için kullanacağız. <img src="/assets/shared/img/ff_getpaywallproductsresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 1.3. Paywallın başarıyla yüklenip yüklenmediğini kontrol edin \{#step-13-add-check-if-the-paywall-uploaded-successfully\} Devam etmeden önce Adapty paywallının başarıyla alındığını doğrulayalım. Alındıysa paywallı ürün verileriyle güncelleyebiliriz. Alınmadıysa hatayı ele alacağız. Kontrolü şu şekilde ekleyebilirsiniz: 1. **+** simgesine tıklayın ve **Add Conditional**'a tıklayın. <img src="/assets/shared/img/ff-add-conditional.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Action Output** bölümünde, daha önce oluşturulan eylem çıktı değişkenini seçin (örneğimizde `getPaywallResult`). <img src="/assets/shared/img/ff-getpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adapty paywallının alındığını doğrulamak için bir değere sahip bir alanın varlığını kontrol edin. Alanları aşağıdaki gibi doldurun: - **Available Options**: Has Field - **Field (AdaptyGetPaywallResult)**: value 4. Koşulu sonlandırmak için **Confirm**'e tıklayın. ## Adım 1.4. Paywall görüntülemesini kaydedin \{#step-14-log-the-paywall-review\} Adapty analitiğinin paywall görüntülemesini takip etmesini sağlamak için bu olayı kaydetmemiz gerekiyor. Bu adım olmadan görüntüleme analitikte sayılmayacaktır. İşte nasıl yapılacağı: 1. **TRUE** etiketi altındaki **+** simgesine tıklayın ve **Add Action**'a tıklayın. 2. **Select Action** alanında **logShowPaywall** eylemini arayın ve seçin. <img src="/assets/shared/img/ff-logshowpaywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Set Action Arguments** alanında **Value**'ya tıklayın ve oluşturduğumuz `getPaywallResult` değişkenini seçin. Bu değişken paywall verilerini içerir. 4. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structured Field - **Select Field**: value 5. **Confirm**'e tıklayın. <img src="/assets/shared/img/ff-lohsgowpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 1.5. Paywall alınamazsa hata gösterin \{#step-15-show-error-if-paywall-not-received\} Adapty paywallı alınamazsa [hatayı ele almanız](error-handling-on-flutter-react-native-unity#system-storekit-codes) gerekir. Bu örnekte sadece bir uyarı mesajı görüntüleyeceğiz. 1. **FALSE** etiketine bir **Informational Dialog** eylemi ekleyin. 2. **Title** alanına, iletişim kutusu başlığı olarak görmek istediğiniz metni ekleyin. Bu örnekte **Error**. 3. **Message** kutusunda **Value**'ya tıklayın. 4. Alanları aşağıdaki gibi doldurun: - **Set Variable**: Oluşturduğumuz `getPaywallProductResult` değişkeni - **Available Options**: Data Structure Field - **Select Field**: error - **Available Options**: Data Structure Field - **Select Field**: errorMessage <img src="/assets/shared/img/ff-error.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Confirm**'e tıklayın. 6. **FALSE** akışına bir **Terminate action** ekleyin. <img src="/assets/shared/img/ff-terminate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Sağ üst köşedeki **Close**'a tıklayın. Tebrikler! Ürün verilerini başarıyla aldınız. Şimdi bunu [FlutterFlow'da tasarladığınız paywalla eşleştirelim](ff-add-variables-to-paywalls). --- # File: ff-add-variables-to-paywalls --- --- title: "Adım 2. Paywall sayfasına veri ekleme" description: "Adapty'de paywallara Feature Flag değişkenleri ekleyin." --- [Gerekli tüm ürün verilerini aldıktan](ff-action-flow) sonra, bu verileri FlutterFlow'da tasarladığınız güzel paywalla eşleştirme zamanı. Bu örnekte ürün başlığını ve fiyatını eşleştireceğiz. ## Adım 2.1. Paywall sayfasına ürün başlığı ekleme \{#step-21-add-product-title-to-paywall-page\} 1. Paywall sayfanızdaki ürün metnine çift tıklayın. **Set from Variable** penceresinde `getPaywallProductResult` değişkenini arayın ve seçin. <img src="/assets/shared/img/ff-paywall-text.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: localizedTitle - **Default Variable Value**: null - **UI Builder Display Value**: Herhangi bir şey; örnekte `product.title` kullanılmıştır. <img src="/assets/shared/img/ff-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Değişiklikleri kaydetmek için **Confirm**'e tıklayın. ## Adım 2.2. Paywall sayfasına fiyat metni ekleme \{#step-22-add-price-text-to-paywall-page\} Fiyat metni için Adım 2.1'deki adımları aşağıda gösterildiği gibi tekrarlayın: 1. Paywall sayfanızdaki fiyat metnine çift tıklayın. **Set from Variable** penceresinde `getPaywallProductResult` değişkenini arayın ve seçin. <img src="/assets/shared/img/ff-price.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: price - **Default Variable Value**: null - **UI Builder Display Value**: Herhangi bir şey; örnekte `product.price` kullanılmıştır. 3. Değişiklikleri kaydetmek için **Confirm** düğmesine tıklayın. ### Paywall sayfasına yerel para biriminde fiyat ekleme \{#add-price-in-local-currency-to-paywall-page\} 1. Paywall sayfanızdaki fiyata çift tıklayın. **Set from Variable** penceresinde `getPaywallProductResult` değişkenini arayın ve seçin. 2. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: price - **Available Options**: Data Structured Field - **Select Field**: amount - **Available Options**: Decimal - **Decimal Type**: Automatic - **Default Variable Value**: null - **UI Builder Display Value**: Herhangi bir şey; örnekte `price.amount` kullanılmıştır. 3. Değişiklikleri kaydetmek için **Confirm**'e tıklayın. İşte bu kadar! Artık uygulamanızı başlattığınızda, Adapty paywallındaki ürün verileri doğrudan paywall sayfanızda görünecek! Şimdi [kullanıcılarınızın bu ürünü satın almasına](ff-make-purchase) izin verme zamanı. --- # File: ff-make-purchase --- --- title: "Adım 3. Satın almayı etkinleştir" description: "Adapty'nin Feature Flags sistemi ile nasıl satın alma yapacağınızı öğrenin." --- Tebrikler! Ürün başlığı ve fiyat dahil olmak üzere [paywallınızı Adapty'den gelen ürün verilerini gösterecek şekilde](ff-add-variables-to-paywalls) başarıyla yapılandırdınız. Şimdi son adıma geçelim – kullanıcıların paywall üzerinden satın alma yapmasını sağlamak. ## Adım 3.1. Kullanıcıların satın alma yapmasını etkinleştir \{#step-31-enable-users-to-make-purchases\} 1. Paywall sayfanızdaki satın al düğmesine çift tıklayın. Sağ panelde, henüz açık değilse **Actions** bölümünü açın. 2. **Action Flow Editor**'ı açın. <img src="/assets/shared/img/ff-action-flow-editor.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Select Action Trigger** penceresinde **On Tap**'i seçin. 4. **No Actions Created** penceresinde **Add Action**'a tıklayın. `makePurchase` eylemini aratın ve seçin. <img src="/assets/shared/img/ff-makepurchase.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Set Actions Arguments** bölümünde, daha önce oluşturulan `getPaywallProductsResult` değişkenini seçin. 6. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structure Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First <img src="/assets/shared/img/ff-makepurchase-value.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. `subscriptionUpdateParameters`'a tıklayın, `AdaptySubscriptionUpdateParameters` ifadesini aratın ve seçin. **Confirm**'e tıklayın. :::info Varsayılan olarak tüm nesne alanlarını boş bırakabilirsiniz. Android uygulamalarında bir aboneliği başka biriyle değiştirmek için bu alanları doldurmanız gerekir. Daha fazla bilgi için [buraya](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) bakın. ::: <img src="/assets/shared/img/ff-subupdate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. **Confirm**'e tıklayın. 9. **Action Output Variable Name** alanında yeni bir değişken oluşturun ve `makePurchaseResult` olarak adlandırın – bu, satın almanın başarılı olduğunu doğrulamak için daha sonra kullanılacak. <img src="/assets/shared/img/ff-makepurchaseresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3.2. Satın almanın başarılı olup olmadığını kontrol et \{#step-32-check-if-the-purchase-was-successful\} Şimdi satın almanın gerçekleşip gerçekleşmediğini kontrol eden bir adım ayarlayalım. 1. **+** simgesine tıklayın ve **Add Conditional**'a tıklayın. 2. **Set Condition for Action** alanında `makePurchaseResult` değişkenini seçin. 3. **Set Variable** penceresinde alanları aşağıdaki gibi doldurun: - **Available Options**: Has Field - **Select Field**: profile <img src="/assets/shared/img/ff-makepurchaseresult-conditional.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm**'e tıklayın. ## Adım 3.3. Ücretli içeriği aç \{#step-33-open-paid-content\} Satın alma başarılıysa ücretli içeriğin kilidini açabilirsiniz. Nasıl yapılacağını aşağıda bulabilirsiniz: 1. **TRUE** etiketinin altındaki **+** simgesine tıklayın ve **Add Action**'a tıklayın. 2. **Define Action** alanında, **Navigate To** listesinden açmak istediğiniz sayfayı aratın ve seçin. Bu örnekte sayfa **Questions**'dır. <img src="/assets/shared/img/ff-questions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3.4. Satın alma başarısız olursa hata mesajı göster \{#step-34-show-error-message-if-purchase-failed\} Satın alma başarısız olursa kullanıcıya bir uyarı gösterelim. 1. **FALSE** etiketine bir **Informational Dialog** eylemi ekleyin. 2. **Title** alanına iletişim kutusu başlığı için istediğiniz metni girin; örneğin **Purchase Failed**. <img src="/assets/shared/img/ff-purchase-fail.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Message** kutusundaki **Value**'ya tıklayın. **Set from Variable** penceresinde `makePurchaseResult` ifadesini aratın ve seçin. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structure Field - **Select Field**: error - **Available Options**: Data Structure Field - **Select Field**: errorMessage <img src="/assets/shared/img/ff-fail-message.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm**'e tıklayın. 5. **FALSE** akışına bir **Terminate** eylemi ekleyin. <img src="/assets/shared/img/ff-terminate-purchase.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Son olarak sağ üst köşedeki **Close**'a tıklayın. Tebrikler! Kullanıcılarınız artık ürünlerinizi satın alabilir. Ek bir adım olarak, ücretli içerik mi yoksa paywall mı gösterileceğine karar vermek amacıyla başka yerlerde [kullanıcının ücretli içeriğe erişimini kontrol eden bir yapı kurmanızı](ff-check-subscription-status) öneririz. --- # File: ff-check-subscription-status --- --- title: "Adım 4. Ücretli içeriğe erişimi kontrol et" description: "Daha iyi kullanıcı segmentasyonu için Adapty'nin özellik bayraklarını kullanarak abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Bir kullanıcının belirli ücretli içeriğe erişimi olup olmadığını belirlerken, onun access level'ını doğrulamanız gerekir. Bu, kullanıcının en az bir access level'a sahip olup olmadığını ve bu level'ın gerekli olan mı olduğunu kontrol etmek anlamına gelir. Bunu, mevcut tüm access level'ları içeren kullanıcı profilini kontrol ederek yapabilirsiniz. Şimdi, kullanıcıların ürününüzü satın almasına izin verelim: 1. Ücretli içeriği göstermesi gereken butona çift tıklayın ve henüz açık değilse sağ paneldeki **Actions** bölümünü açın. 2. **Action Flow Editor**'ı açın. <img src="/assets/shared/img/ff-open-paid-content.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Select Action Trigger** penceresinde **On Tap** seçeneğini seçin. 4. **No Actions Created** penceresinde **Add Conditional Action** butonuna tıklayın. 5. Eylem argümanlarını ayarlamak için **UNSET**'e tıklayın ve `currentProfile` değişkenini seçin. Bu, geçerli kullanıcının profil verilerini tutan Adapty değişkenidir. <img src="/assets/shared/img/ff-currentprofile.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Alanları aşağıdaki gibi doldurun: - **Available Options**: Data Structure Field - **Select Field**: accessLevels - **Available Options**: Filter List Items - **Filter Conditions**: 1. **Conditions -> Single Condition** seçeneğini seçin ve **UNSET**'e tıklayın. 2. **First value** alanında **Source** olarak **Item in list** seçin ve alanları şu şekilde doldurun: - **Available Options**: Data Structure Field - **Select Field**: accessLevelIdentifier 3. Filtre operatörünü **Equal to** olarak ayarlayın. 4. **Second value** yanındaki **UNSET**'e tıklayın ve **Value** alanına access level'ınızın ID'sini girin; örneğimizde `premium` kullanıyoruz. <img src="/assets/shared/img/ff-filter.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Confirm**'e tıklayın ve aşağıdaki diğer alanları doldurmaya devam edin. - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structure Field - **Select Field**: accessLevel - **Available Options**: Data Structure Field - **Select Field**: isActive 7. **Confirm**'e tıklayın. Şimdi, sonraki adım için eylemleri ekleyin — kullanıcının doğru aboneliğe sahip olup olmadığına göre. Ya onları premium abonelere açık olan sayfaya yönlendirin ya da erişim satın alabilmeleri için paywall sayfasını açın. --- # File: ff-resources --- --- title: "Adapty FlutterFlow eklentisi eylemleri ve veri türleri" description: "Abonelik tabanlı özellikleri kolaylaştırmak için Adapty'nin özellik bayrağı kaynaklarına erişin." --- ## Özel Aksiyonlar \{#custom-actions\} Aşağıda, Adapty eklentisiyle FlutterFlow'a sunulan Adapty metodları yer almaktadır. Bunlar FlutterFlow'da özel aksiyon olarak kullanılabilir. | Özel Eylem | Açıklama | Eylem Argümanları | Adapty Veri Türleri - Eylem Çıktı Değişkeni | |---|----|--------|----| | activate | Adapty SDK'yı başlatır | Yok || | <p id="getPaywall">getPaywall</p> | Bir paywall getirir. Paywall ürünlerini döndürmez. Gerçek ürünleri almak için `getPaywallProducts` eylemini kullanın | <ul><li>[Placement_ID](placements)</li><li>[Locale](localizations-and-locale-codes)</li></ul> | [AdaptyGetPaywallResult](ff-resources#adaptygetpaywallresult)| | <p id="getPaywallProducts">getPaywallProducts</p> | Gerçek paywall ürünlerinin listesini döndürür | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyGetProductsResult](ff-resources#adaptygetproductsresult) | | <p id="getproductsintroductoryoffereligibility">getProductsIntroductoryOfferEligibility</p> | Kullanıcının iOS abonelik başlangıç teklifine uygun olup olmadığını kontrol eder | [AdaptyPaywallProduct](product) | [AdaptyGetIntroEligibilitiesResult](ff-resources#adaptygetintroeligibilitiesresult) | | <p id="makePurchase">makePurchase</p> | Satın alma işlemini tamamlar ve içeriğin kilidini açar. Paywall'da bir promosyon teklifi varsa Adapty bunu ödeme sırasında otomatik olarak uygular | <ul><li> **product**: Paywall'dan alınan bir AdaptyPaywallProduct nesnesi.</li><li> **subscriptionUpdateParams**: Aboneliği yükseltmek veya düşürmek için kullanılan bir [`AdaptySubscriptionUpdateParameters`](ff-resources#adaptysubscriptionupdateparameters) nesnesi (Android için kullanın).</li><li>**isOfferPersonalized**: Teklifin alıcıya özel olup olmadığını belirtir (Android için kullanın).</li></ul> | [AdaptyMakePurchaseResult](ff-resources#adaptymakepurchaseresult) | | <p id="getprofile">getProfile</p> | <p>Mevcut uygulama kullanıcısının profilini getirir. Bu sayede access level'ları ve diğer parametreleri ayarlayabilirsiniz</p><p>Başarısız olursa (örneğin internet yoksa) önbelleğe alınmış veriler döndürülür. Adapty, bilgilerin mümkün olduğunca güncel kalması için profil önbelleğini düzenli olarak günceller</p> | Yok | [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | updateProfile | Mevcut kullanıcı profilinin e-posta, telefon numarası vb. isteğe bağlı özelliklerini değiştirir. Bu özellikleri daha sonra kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz | [AdaptyProfile](ff-resources#adaptyprofile) için ID ve güncellenmesi gereken parametreler | [AdaptyError](ff-resources#adaptyerror) (İsteğe Bağlı) | | restorePurchases | Kullanıcının daha önce yaptığı tüm satın almaları geri yükler | Yok | [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | logShowPaywall | Kullanıcıya belirli bir paywall gösterildiğinde bunu kaydeder | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyError](ff-resources#adaptyerror) (İsteğe Bağlı) | | identify | Kullanıcıyı sisteminizdeki `customerUserId` ile tanımlar | customerUserId | [AdaptyError](ff-resources#adaptyerror) (İsteğe Bağlı) | | logout | Mevcut kullanıcının uygulamadan oturumunu kapatır | Yok | [AdaptyError](ff-resources#adaptyerror) (İsteğe Bağlı)| | presentCodeRedemptionSheet | Kullanıcıların kod kullanmasına olanak tanıyan bir sayfa görüntüler (yalnızca iOS) | Yok | Yok | ## Veri Tipleri \{#data-types\} Adapty eklentisiyle FlutterFlow'a iletilen Adapty veri tipleri (veri değerleri koleksiyonları). ### AdaptyAccessLevel Kullanıcının [access level](access-level) bilgisi. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | activatedAt | DateTime | Bu access level'ın etkinleştirildiği zaman | | activeIntroductoryOfferType | String | Aktif başlangıç teklifinin türü. Ayarlanmışsa, bu abonelik döneminde bir teklif uygulandığı anlamına gelir | | activePromotionalOfferId | String | Aktif promosyon teklifinin kimliği (iOS'tan satın alınan) | | activePromotionalOfferType | String | Aktif promosyon teklifinin türü (iOS'tan satın alınan). Ayarlanmışsa, bu abonelik döneminde bir teklif uygulandığı anlamına gelir | | billingIssueDetectedAt | DateTime | Bir fatura sorununun tespit edildiği zaman. Abonelik hâlâ aktif olabilir. Ödeme başarıyla işlenirse null olarak ayarlanır | | cancellationReason | String | Aboneliğin iptal edilme nedeni | | expiresAt | DateTime | Access level'ın sona erme zamanı (geçmişte olabilir ya da süresiz erişim için ayarlanmamış olabilir) | | id | String | Access level'ın tanımlayıcısı | | isActive | Boolean | Bu access level aktifse true. Genel olarak, kullanıcının premium özelliklere erişimi olup olmadığını belirlemek için bu özelliği kontrol edebilirsiniz | | isInGracePeriod | Boolean | Bu otomatik yenilenen abonelik [ek süre](https://developer.apple.com/help/app-store-connect/manage-subscriptions/enable-billing-grace-period-for-auto-renewable-subscriptions) içindeyse true | | isLifetime | Boolean | Bu access level süresiz olarak aktifse true (son kullanma tarihi yok) | | isRefund | Boolean | Bu satın alma iade edildiyse true | | offerId | String | Aktif promosyon teklifinin kimliği (Android'den satın alınan) | | renewedAt | DateTime | Access level'ın en son yenilendiği zaman | | startsAt | DateTime | Bu access level'ın başlangıç zamanı (gelecekte olabilir) | | store | String | Satın almanın yapıldığı mağaza | | unsubscribedAt | DateTime | Abonelik için otomatik yenilemenin kapatıldığı zaman. Abonelik hâlâ aktif olabilir. Ayarlanmamışsa, kullanıcı aboneliği yeniden etkinleştirmiştir | | vendorProductId | String | Bu access level'ı açan mağazadaki ürün kimliği | | willRenew | Boolean | Bu otomatik yenilenen abonelik yenilenecek şekilde ayarlanmışsa true | ### AdaptyAccessLevelIdentifiers Bu struct, `Map<String, AdaptyAccessLevel` [AdaptyAccessLevel](ff-resources#adaptyaccesslevel) için anahtar-değer çiftinin yerine geçmek amacıyla tasarlanmıştır. | Alan Adı | Tür | Açıklama | |------------|------|-------------| | accessLevelIdentifier | String | Access level'ın ID'si | | accessLevel | Data ([AdaptyAccessLevel](ff-resources#adaptyaccesslevel)) | İlişkili [AdaptyAccessLevel](ff-resources#adaptyaccesslevel) | ### AdaptyCustomDoubleAttribute [Kullanıcı](ff-resources#adaptyprofile) için tanımlanmış özel double attribute bilgileri. | Alan Adı | Tür | Açıklama | |------------|------|-------------| | key | String | Özel double attribute'un ID'si | | value | Double | Özel double attribute'un değeri | ### AdaptyCustomStringAttribute [Kullanıcı](ff-resources#adaptyprofile) için tanımlanmış özel string attribute'larına ilişkin bilgiler. | Alan Adı | Tür | Açıklama | |------------|------|-------------| | key | String | Özel string attribute'un ID'si | | value | String | Özel string attribute'un değeri | ### AdaptyError Bir hata hakkındaki ayrıntıları içerir. Hata kodlarının tam listesi için bkz. [React Native, Flutter, Unity - Hataları yönetme](error-handling-on-flutter-react-native-unity). | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | errorMessage | String | Hatanın okunabilir açıklaması | | errorCode | Integer | Hatayı tanımlayan sayısal kod | ### AdaptyGetIntroEligibilitiesResult `getProductsIntroductoryOfferEligibility` özel eyleminin sonucunu içerir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | value | List < Data ([AdaptyProductIntroEligibility](ff-resources#adaptyproductintroeligibility)) > | Kullanıcının promosyon tekliflerine uygunluk listesi | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [`AdaptyError`](ff-resources#adaptyerror) aracılığıyla hata ayrıntılarını içerir | ### AdaptyGetPaywallResult `getPaywall` özel eyleminin sonucunu içerir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | value | Data ([AdaptyPaywall](ff-resources#adaptypaywall)) | [AdaptyPaywall](ff-resources#adaptypaywall) nesnelerinin listesini içerir | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [AdaptyError](ff-resources#adaptyerror) aracılığıyla hata bilgisi içerir | ### AdaptyGetProductsResult `getPaywallProducts` özel eyleminin sonucunu içerir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | value | List < Data ([AdaptyPaywallProduct](product)) > | [AdaptyPaywallProduct](product) listesini içerir | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [AdaptyError](ff-resources#adaptyerror) aracılığıyla hata bilgisini içerir | ### AdaptyGetProfileResult `getProfile` özel eyleminin sonucunu içerir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | value | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | Kullanıcı profilini bir [AdaptyProfile](ff-resources#adaptyprofile) olarak içerir | | error | Data (AdaptyError) | Hata bilgisini [AdaptyError](ff-resources#adaptyerror) aracılığıyla içerir | ### AdaptyMakePurchaseResult `makePurchase` özel eyleminin sonucunu içerir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | value | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | Kullanıcının profilini [AdaptyProfile](ff-resources#adaptyprofile) olarak içerir | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | Hata bilgisini [AdaptyError](ff-resources#adaptyerror) aracılığıyla içerir | ### AdaptyNonSubscription Abonelik dışı satın almalar hakkında bilgi. Bunlar tek seferlik (consumable) ürünler, kilit açma işlemleri (oyunda yeni harita açma gibi) vb. olabilir. | Alan Adı | Tür | Açıklama | |--------------------------|----------|-------------| | isConsumable | Boolean | Ürünün consumable olup olmadığını belirtir | | isOneTime | Boolean | Ürünün tek seferlik satın alma olup olmadığını belirtir (örneğin, true ise satın alma yalnızca bir kez işlenir) | | isRefund | Boolean | Ürünün iade edilip edilmediğini belirtir | | isSandbox | Boolean | Ürünün sandbox ortamında satın alınıp alınmadığını belirtir | | purchasedAt | DateTime | Ürünün satın alındığı zaman | | purchaseId | String | Adapty'deki satın almanın kimliği. Tek seferlik ürünleri takip etmek için kullanılabilir | | store | String | Ürünün satın alındığı mağaza (örneğin, App Store, Google Play) | | vendorProductId | String | Ürünün satıcı sistemindeki kimliği | | vendorTransactionId | String | Satıcı sistemindeki işlem kimliği | ### AdaptyPaywall Bir [paywall](paywalls) hakkındaki bilgiler. | Alan Adı | Tür | Açıklama | |----------------------|----------|-------------| | abTestName | String | Üst A/B testinin adı | | hasViewConfiguration | Boolean | Paywall için bir görünüm yapılandırması olup olmadığını gösterir | | locale | String | Paywallın locale ID'si | | name | String | Paywall adı | | placement.id | String | Üst placement'ın ID'si | | remoteConfigString | String | Bu paywall ile ilişkilendirilmiş, Adapty Kontrol Paneli'nden gelen özel sözlük | | placement.revision | Integer | Paywallın mevcut revizyon/sürüm numarası. Her değişiklik yeni bir revizyon oluşturur | | variationId | String | Satın almaları bu paywalla atfetmek için kullanılan varyasyon ID'si | | vendorProductIds | String | Paywall ile ilişkili ürün ID'lerinin dizisi | ### AdaptyPaywallProduct [Ürün](product) hakkında bilgi. | Alan Adı | Tür | Açıklama | | -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | vendorProductId | String | Uygulama mağazasındaki bir ürünün ID'si | | localizedDescription | String | Ürünün kullanıcının dilindeki açıklaması | | localizedTitle | String | Ürünün kullanıcının dilindeki adı | | regionCode | String | Ürün fiyatını biçimlendirmek için kullanılan yerel ayarın bölge kodu (iOS için kullanın) | | isFamilyShareable | Boolean | Ürünün App Store Connect'te aile paylaşımına açık olup olmadığını belirten Boolean değeri. iOS 14.0 ve macOS 11.0 altındaki sürümler için her zaman FALSE olur (iOS için kullanın) | | paywallVariationId | String | Satın almaları bu paywall'a atıflamak için kullanılan varyant ID'si | | paywallABTestName | String | Bağlı A/B testi adı | | paywallName | String | Bağlı paywall adı | | price | Data ([AdaptyPriceData](#adaptyprice)) | Ürünün fiyatı | | subscriptionDetails | Data ([AdaptySubscriptionDetails](#adaptysubscriptiondetails)) | Abonelik bilgileri | ### AdaptyPrice Ürün fiyatına ilişkin bilgiler. | Alan Adı | Tür | Açıklama | | --------------- | ------ | --------------------------------------------- | | amount | Double | Fiyatın sayısal değeri | | currencyCode | String | Fiyat para biriminin kodu | | currencySymbol | String | Para birimi için kullanılan sembol | | localizedString | String | Kullanıcının diline göre gösterilen fiyat | ### AdaptyProductIntroEligibility Kullanıcının bir iOS aboneliği için başlangıç teklifine uygun olup olmadığını tanımlar. | Alan Adı | Tür | Açıklama | | ---------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | | vendorProductId | String | Uygulama mağazasındaki bir ürünün ID'si | | eligibility | [AdaptyEligibilityEnum](ff-resources#adaptyeligibilityenum) | Kullanıcının bir iOS aboneliği için başlangıç teklifine uygun olup olmadığının tanımı | ### AdaptyProductNonsubscriptions Bu ürüne bağlı aktif abonelik dışı satın almanın ayrıntıları. | Alan Adı | Tür | Açıklama | | ---------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | | productId | String | Uygulama mağazasındaki ürünün ID'si | | nonsubscriptions | [AdaptyNonSubscription](ff-resources#adaptynonsubscription) | Abonelik dışı satın almalar hakkında bilgi. Bunlar tek seferlik (consumable) ürünler, kilit açma öğeleri (oyunda yeni harita açma gibi) vb. olabilir. | ### AdaptyProductSubscriptions Bu ürünle ilişkili aktif aboneliğin ayrıntıları. | Alan Adı | Tür | Açıklama | | ------------ | ----------------------------------------------------- | ----------------------------------------------- | | productId | String | Uygulama mağazasındaki ürünün kimliği | | subscription | [AdaptySubscription](ff-resources#adaptysubscription) | Abonelik satın alımlarına ilişkin bilgiler | ### AdaptyProfile Kullanıcının profil bilgileri | Alan Adı | Tür | Açıklama | | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | accessLevels | List < Data ([AdaptyAccessLevelIdentifiers](ff-resources#adaptyaccesslevelidentifiers)) > | Kullanıcıya ait tüm access level'ların listesi | | profileId | String | Kullanıcı profilinin ID'si | | customerUserId | String | Kullanıcının satıcı sistemindeki ID'si | | subscriptions | List < Data ([MapKeySubscriptions](#mapkeysubscriptions)) > | Kullanıcının satın aldığı tüm aboneliklerin listesi | | nonSubscriptions | List < Data ([MapKeyNonSubscriptions](#mapkeynonsubscriptions)) > | Kullanıcının satın aldığı tüm abonelik dışı ürünlerin listesi | ### AdaptyProfileParameters \{#adaptyprofileparameters\} Kullanıcı hakkında bilgiler. | Alan Adı | Tür | Açıklama | | ----------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | firstName | String | Kullanıcının adı | | lastName | String | Kullanıcının soyadı | | gender | [AdaptyGenderEnum](#adaptygenderenum) | Kullanıcının cinsiyeti | | birthday | String | Kullanıcının doğum tarihi | | email | String | Kullanıcının e-posta adresi | | phoneNumber | String | Kullanıcının telefon numarası | | facebookAnonymousId | String | Kullanıcının [Facebook Ads entegrasyonundaki](facebook-ads) kimliği | | amplitudeUserId | String | Kullanıcının [Amplitude entegrasyonundaki](amplitude) kimliği | | amplitudeDeviceId | String | Kullanıcının cihazının [Amplitude entegrasyonundaki](amplitude) kimliği | | mixpanelUserId | String | Kullanıcının [Mixpanel entegrasyonundaki](mixpanel) kimliği | | appmetricaProfileId | String | Kullanıcının [AppMetrica entegrasyonundaki](appmetrica) kimliği | | appmetricaDeviceId | String | Kullanıcının cihazının [AppMetrica entegrasyonundaki](appmetrica) kimliği | | oneSignalPlayerId | String | Kullanıcının [OneSignal entegrasyonundaki](onesignal) kimliği | | pushwooshHWID | String | Kullanıcının cihazının [Pushwoosh entegrasyonundaki](pushwoosh) kimliği | | firebaseAppInstanceId | String | Kullanıcının [Firebase entegrasyonundaki](firebase-and-google-analytics) kimliği | | airbridgeDeviceId | String | Kullanıcının cihazının [Airbridge entegrasyonundaki](airbridge) kimliği | | appTrackingTransparencyStatus | AdaptyATTStatus | IDFA erişiminin durumu (iOS için kullanın) | | analyticsDisabled | Boolean | Kullanıcı için [harici analitiğin devre dışı bırakılıp bırakılmadığını](analytics-integration#disabling-external-analytics-for-a-specific-customer) belirtir | | customStringAttributes | List < Data ([AdaptyCustomStringAttribute](ff-resources#adaptycustomstringattribute)) > | Kullanıcının özel string özelliklerinin listesi | | customDoubleAttributes | List < Data ([AdaptyCustomDoubleAttribute](ff-resources#adaptycustomdoubleattribute)) > | Kullanıcının özel double özelliklerinin listesi | ### AdaptySubscription Kullanıcının mevcut aboneliğine ilişkin bilgiler. | Alan Adı | Tür | Açıklama | | --------------------------- | -------- | ------------------------------------------------------------ | | activatedAt | DateTime | Bu aboneliğin etkinleştirildiği zaman | | activeIntroductoryOfferType | String | Aktif başlangıç teklifinin türü. Ayarlanmışsa, bu abonelik döneminde bir teklif uygulandığı anlamına gelir | | activePromotionalOfferId | String | Aktif promosyon teklifinin kimliği (iOS için kullanın) | | activePromotionalOfferType | String | Aktif promosyon teklifinin türü (iOS için kullanın). Ayarlanmışsa, bu abonelik döneminde bir teklif uygulandığı anlamına gelir | | cancellationReason | String | Aboneliğin iptal edilme nedeni | | expiresAt | DateTime | Aboneliğin sona erme zamanı | | renewedAt | DateTime | Aboneliğin en son yenilendiği zaman | | unsubscribedAt | DateTime | Abonelik için otomatik yenilemenin kapatıldığı zaman. Abonelik hâlâ aktif olabilir. Ayarlanmamışsa, kullanıcı aboneliği yeniden etkinleştirmiştir | | billingIssueDetectedAt | DateTime | Ödeme sorununun tespit edildiği zaman. Abonelik hâlâ aktif olabilir. Ödeme başarıyla işlenirse null olarak ayarlanır | | isActive | Boolean | Bu abonelik aktifse True. Genel olarak, kullanıcının premium özelliklere erişimi olup olmadığını belirlemek için bu özelliği kontrol edebilirsiniz | | isInGracePeriod | Boolean | Bu otomatik yenilenen abonelik [ek süre](https://developer.apple.com/help/app-store-connect/manage-subscriptions/enable-billing-grace-period-for-auto-renewable-subscriptions) içindeyse True | | isLifetime | Boolean | Bu abonelik süresiz erişim için aktifse True (son kullanma tarihi yok) | | isRefund | Boolean | Bu satın alma iade edildiyse True | | isSandbox | Boolean | Ürünün sandbox ortamında satın alınıp alınmadığını gösterir | | offerId | String | Aktif promosyon teklifinin kimliği (Android için kullanın) | | startsAt | DateTime | Bu access level'ın başlangıç zamanı (gelecekte olabilir) | | store | String | Ürünün satın alındığı mağaza (ör. App Store, Google Play) | | vendorOriginalTransactionId | String | Satıcı sistemindeki ilk aboneliğin kimliği | | vendorProductId | String | Satıcı sistemindeki ürünün kimliği | | vendorTransactionId | String | Satıcı sistemindeki işlem kimliği | | willRenew | Boolean | Bu otomatik yenilenen abonelik yenilenecek şekilde ayarlandıysa True | ### AdaptySubscriptionDetails [AdaptyPaywallProduct](product) nesnesinin bir parçası olan Subscription nesnesinin şeması. | Alan Adı | Tür | Açıklama | | ----------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | androidBasePlanId | String | Google Play Store'daki [temel plan ID'si](https://support.google.com/googleplay/android-developer/answer/12154973) veya Stripe'taki [fiyat ID'si](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices). | | androidIntroductoryOfferEligibility | [AdaptyEligibilityEnum](ff-resources#adaptyeligibilityenum) | Kullanıcının bir iOS aboneliği için başlangıç teklifine uygun olup olmadığının tanımı | | androidOfferId | String | Etkin bir promosyon teklifinin ID'si (Android için kullanın) | | androidOfferTags | List < String > | Temel planlar ve abonelik teklifleri için belirtilen [özel etiketlerin](https://developers.google.com/android-publisher/api-ref/rest/v3/OfferTag) listesi. | | introductoryOffer | List < Data ([AdaptySubscriptionPhase](ff-resources#adaptysubscriptionphase)) > | Başlangıç teklifinin ID'si (iOS için kullanın) | | localizedSubscriptionPeriod | String | Kullanıcının dilinde abonelik dönemi | | promotionalOffer | Data ([AdaptySubscriptionPhase](ff-resources#adaptysubscriptionphase)) | Promosyon teklifi ayrıntıları (iOS için kullanın) | | promotionalOfferEligibility | Boolean | Kullanıcının bir iOS aboneliği için promosyon teklifine uygun olup olmadığının tanımı | | promotionalOfferId | String | Promosyon teklifinin ID'si (iOS için kullanın) | | renewalType | [AdaptyRenewalTypeEnum](#adaptyrenewaltypeenum) | Aboneliğin otomatik yenilenip yenilenmediğini [AdaptyRenewalTypeEnum](ff-resources#adaptyrenewaltypeenum) aracılığıyla tanımlar | | subscriptionGroupIdentifier | String | Ürünün ait olduğu ürün grubunun ID'si (iOS için kullanın) | | subscriptionPeriod | Data ([AdaptySubscriptionPeriod](#adaptysubscriptionperiod)) | Aboneliğin süresi | ### AdaptySubscriptionPeriod Aboneliğin süresi. | Alan Adı | Tür | Açıklama | | ------------- | --------------------------------------------- | ------------------------------------------------------------------ | | numberOfUnits | Integer | Aboneliğin kaç gün/hafta/ay/yıl süreceği. | | unit | [AdaptyPeriodUnitEnum](#adaptyperiodunitenum) | Dönemin ölçüm birimi: gün, hafta, ay veya yıl. | ### AdaptySubscriptionPhase Bir abonelik aşamasını temsil eder; örneğin ücretsiz deneme veya başlangıç teklifi dönemi. | Alan Adı | Tür | Açıklama | | --------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | identifier | String | Aşamanın ID'si | | localizedNumberOfPeriods | String | Aşamanın süresi. Örneğin, 6 aylık bir teklif kullanıcının dilinde `6 months` olarak görüntülenir. | | localizedSubscriptionPeriod | String | Kullanıcının dilinde abonelik süresi, örneğin `3 months`. | | numberOfPeriods | Integer | Bu aşamadaki abonelik dönemi sayısı. Örneğin, 6 aylık bir teklifin iki adet 3 aylık dönemi olur. | | paymentMode | [AdaptyPaymentModeEnum](#adaptypaymentmodeenum) | Bu aşama için kullanılan ödeme modeli. | | price | Data ([AdaptyPrice](#adaptyprice)) | Bu aşamanın fiyatı. | | subscriptionPeriod | Data ([AdaptySubscriptionPeriod](#adaptysubscriptionperiod)) | Bu aşamanın dayandığı abonelik dönemi. | ### AdaptySubscriptionUpdateParameters (*Yalnızca Android*) Bir aboneliği başka bir abonelikle değiştirmek için kullanılan parametreler. | Alan Adı | Tür | Açıklama | | ---------- | ------------------------------------------------------------ | ---------- | | oldSubVendorProductId | String | Play Store'da değiştirmek istediğiniz mevcut aboneliğin ID'si. | | replacementMode | [AdaptySubscriptionUpdateReplacementMode](ff-resources#adaptysubscriptionupdatereplacementmode) | [`BillingFlowParams.ProrationMode`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode) değerlerine karşılık gelen enum. | ### MapKeyNonSubscriptions [AdaptyNonSubscription](ff-resources#adaptynonsubscription) için bir sözlüğün yerine geçer. | Alan Adı | Tür | | -------- | ------------------------------------------------------------ | | key | String | | value | List < Data ([AdaptyNonSubscription](ff-resources#adaptynonsubscription)) > | ### MapKeySubscriptions [AdaptySubscription](ff-resources#adaptysubscription) için bir sözlüğün yerine geçen yapı. | Alan Adı | Tür | | -------- | ------------------------------------------------------------ | | key | String | | value | List < Data ([AdaptySubscription](ff-resources#adaptysubscription)) > | ## Enum'lar \{#enums\} Adapty plugin'i aracılığıyla FlutterFlow'a iletilen Adapty enum'ları (önceden tanımlanmış sabitler kümesi olan değişkenler). ### AdaptyEligibilityEnum Kullanıcının bir iOS aboneliği için başlangıç teklifine uygun olup olmadığını belirtir. | Alan Adı | Açıklama | |--------------------------|-------------| | eligible | Kullanıcı başlangıç teklifine uygundur, bu bilgiyi arayüzünüzde göstermek güvenlidir | | ineligible | Kullanıcı herhangi bir teklif almaya uygun değildir, arayüzünüzde göstermemelisiniz | | notApplicable | Bu ürün bir teklif sunacak şekilde yapılandırılmamıştır | ### AdaptyGenderEnum Kullanıcının cinsiyetini tanımlar. | Alan Adı | Açıklama | | -------- | ------------------------------------------------- | | none | Cinsiyet belirlenmemiş | | female | Kullanıcının cinsiyeti kadın | | male | Kullanıcının cinsiyeti erkek | | Other | Kullanıcı cinsiyetini "diğer" olarak belirlemiş | ### AdaptyPaymentModeEnum Ödeme modelini tanımlar. | Alan Adı | Açıklama | | ---------- | ------------------------------------------------------------ | | payAsYouGo | Müşterilerin sabit bir ücret ödemek yerine, ürün/hizmeti gerçek kullanımlarına göre faturalandırıldığı bir fiyatlandırma modeli | | payUpFront | Müşterilerin ürün/hizmeti almadan önce faturalandırıldığı bir fiyatlandırma modeli. | | freeTrial | Kullanıcı ücretsiz deneme sürecinde | | unknown | Fiyatlandırma modeli tanımlanmamış | ### AdaptyPeriodUnitEnum Dönemlerin ölçüldüğü birimleri tanımlar. | Alan Adı | Açıklama | | -------- | ------------- | | day | Gün cinsinden | | week | Hafta cinsinden | | month | Ay cinsinden | | year | Yıl cinsinden | | unknown | Tanımsız | ### AdaptyRenewalTypeEnum Aboneliğin otomatik yenilenip yenilenmediğini tanımlar. | Alan Adı | Açıklama | | ------------- | ----------------------------------------------------------- | | prepaid | Abonelik ön ödemeli ve otomatik yenilenmiyor. | | autorenewable | Abonelik otomatik yenileniyor. | ### AdaptySubscriptionUpdateReplacementMode Android için abonelik güncelleme modunu tanımlar. | Alan Adı | Açıklama | | ------------- | --------------------------------------------------- | | withTimeProration | (varsayılan) Yeni plan hemen devreye girer ve kalan süre orantılı hesaplanarak kullanıcıya kredi olarak yansıtılır. | | chargeProratedPrice | Yeni plan hemen devreye girer ve faturalama döngüsü aynı kalır. Kalan süre için ücret tahsil edilir. Bu seçenek yalnızca abonelik yükseltmelerinde kullanılabilir. | | withoutProration | Yeni plan hemen devreye girer ve yeni fiyat bir sonraki yenileme tarihinde tahsil edilir. Faturalama döngüsü aynı kalır. | | deferred | Yeni satın alma hemen geçerli olur; yeni plan ise mevcut öğenin süresi dolduğunda devreye girer. | | chargeFullPrice | Yeni plan hemen devreye girer ve faturalama döngüsü aynı kalır. Kalan süre için ücret tahsil edilir. Bu seçenek yalnızca abonelik yükseltmelerinde kullanılabilir. | ### Uygulama Durumları \{#app-states\} Uygulama durumu değişkenleri, bir uygulamanın mevcut durumunu tutan özel değişkenlerdir. Tüm sayfalar ve bileşenler genelinde, uygulamanın her yerinden erişilebilir ve değiştirilebilirler. Bu tür değişkenler; kullanıcı tercihleri ve kimlik doğrulama token'ları gibi uygulamanın farklı bölümleri arasında paylaşılması gereken verileri saklamak için kullanışlıdır. | Alan Adı | Veri Tipi | Kalıcı | Açıklama | | -------------- | -------------------------------------------------- | --------- | ------------------------------------------------------------ | | currentProfile | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | False | Mevcut kullanıcı profiline ait bilgileri içeren değişken. Güncel tutun. | --- # End of Documentation _Generated on: 2026-07-24T13:02:34.576Z_ _Successfully processed: 277/277 files_ # UNITY - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: tr Generated on: 2026-07-24T13:02:34.584Z Total files: 41 --- # File: sdk-installation-unity --- --- title: "Unity SDK'yı Yükleyin ve Yapılandırın" description: "Unity için Adapty SDK'yı abonelik tabanlı uygulamalara adım adım yükleme kılavuzu." --- Adapty SDK, Unity uygulamanıza sorunsuz entegrasyon için iki temel modül içerir: - **Core Adapty**: Adapty'nin uygulamanızda düzgün çalışması için gerekli olan temel SDK'dır. - **AdaptyUI**: [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız bu modüle ihtiyacınız vardır. Paywall Builder, kolayca cross-platform paywall oluşturmanızı sağlayan kullanıcı dostu, kodsuz bir araçtır. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Paywall görüntüleme, satın alma yapma ve diğer temel işlevleri içeren tam kurulumu gösteren [örnek uygulamamıza](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets) göz atın. ::: ## Gereksinimler \{#requirements\} Adapty SDK, iOS 13.0 ve üzerini destekler; ancak paywall builder ile oluşturulan paywalllarla çalışmak için iOS 15.0+ gereklidir. :::info Adapty, Google Play Billing Library'nin 8.x sürümüne kadar olan versiyonlarıyla uyumludur. Varsayılan olarak Adapty, Google Play Billing Library v7.0.0 kullanır. Daha yeni bir sürüm kullanmak için Android build'inizdeki [Billing bağımlılığını geçersiz kılın](https://developer.android.com/google/play/billing/integrate#dependency). ::: :::info SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır. ::: ## Adapty SDK'yı Yükleyin \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Unity.svg?style=flat&logo=unity)](https://github.com/adaptyteam/AdaptySDK-Unity/releases) Tercih ettiğiniz kurulum yöntemini seçin: <Tabs groupId="unity-install-method"> <TabItem value="git-url" label="Git URL"> Adapty SDK'yı Unity Package Manager aracılığıyla Git URL kullanarak yükleyin: 1. Unity'de **Window → Package Manager** bölümünü açın. 2. Sol üst köşedeki **+** düğmesine tıklayın, ardından **Add package from git URL...** seçeneğini seçin. 3. Aşağıdaki URL'yi girin ve **Add** düğmesine tıklayın: ``` https://github.com/adaptyteam/AdaptySDK-Unity.git?path=Packages/com.adapty.unity-sdk#upm ``` Ayrıntılar için Unity'nin [Git URL'sinden UPM paketi yükleme](https://docs.unity3d.com/Manual/upm-ui-giturl.html) rehberine bakın. </TabItem> <TabItem value="unity-package" label="Unity package" default> [`adapty-unity-plugin-*.unitypackage`](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Releases) dosyasını GitHub'dan indirin ve projenize içe aktarın. <img src="/assets/shared/img/456bd98-adapty-unity-plugin.webp" style={{ border: 'none', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </TabItem> </Tabs> SDK'yı yükledikten sonra aşağıdaki adımları tamamlayın: 1. [External Dependency Manager (EDM) eklentisini](https://github.com/googlesamples/unity-jar-resolver#getting-started) yükleyin. Adapty SDK, iOS Cocoapods bağımlılıklarını ve Android gradle bağımlılıklarını yönetmek için bunu kullanır. 2. EDM'yi yükledikten sonra bağımlılık yöneticisini çağırmanız gerekebilir: `Assets -> External Dependency Manager -> Android Resolver -> Force Resolve` ve `Assets -> External Dependency Manager -> iOS Resolver -> Install Cocoapods` 3. Unity projenizi iOS için derlerken `Unity-iPhone.xcworkspace` dosyasını elde edersiniz; Cocoapods bağımlılıklarının kullanılabilmesi için `Unity-iPhone.xcodeproj` yerine bu dosyayı açmanız gerekir. ## Adapty SDK'nın Adapty modülünü etkinleştirme \{#activate-adapty-module-of-adapty-sdk\} Adapty SDK'yı uygulama kodunuzda etkinleştirin. :::note Adapty SDK, uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir. ::: **Public SDK Key**'inizi almak için: 1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin. 2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil). 3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin. Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın: ``` npm install -g adapty adapty auth login adapty apps list ``` Ya da doğrudan: ``` npx adapty auth login adapty apps list ``` - Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır. - **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun. ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` :::important Diğer Adapty SDK metodlarını çağırmadan önce `Activate` tamamlanma callback'ini bekleyin. Tam sıralama için [Unity SDK'da Çağrı Sırası](unity-sdk-call-order) sayfasına bakın. ::: ## Olay dinlemeyi ayarlayın \{#set-up-event-listening\} Adapty olaylarını dinlemek için bir script oluşturun. Sahnenizde bu nesneye `AdaptyListener` adını verin. Uygulamanın yaşam süresi boyunca kalıcı olmasını sağlamak için bu nesneye `DontDestroyOnLoad` metodunu kullanmanızı öneririz. <img src="/assets/shared/img/2ccd564-create_adapty_listener.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty, `AdaptySDK` isim alanını kullanır. Adapty SDK kullanan script dosyalarınızın en üstüne şunu ekleyebilirsiniz: ```csharp showLineNumbers title="C#" using AdaptySDK; ``` Adapty olaylarına abone olun: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle updated profile data } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` Script Execution Order ayarını, AdaptyListener'ı Default Time'ın önüne gelecek şekilde düzenlemenizi öneririz. Bu sayede Adapty mümkün olduğunca erken başlatılır. <img src="/assets/shared/img/activate_unity.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Şimdi uygulamanızda paywallları ayarlayın: - [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](unity-quickstart-paywalls) takip edin. - Kendi paywall arayüzünüzü oluşturuyorsanız, [özel paywall'lar için hızlı başlangıç kılavuzuna](unity-quickstart-manual) bakın. ## Adapty SDK'nın AdaptyUI modülünü etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\} [Paywall Builder](adapty-paywall-builder) kullanmayı planlıyor ve AdaptyUI modülünü yüklediyseniz AdaptyUI'ın etkin olması gerekir. Yapılandırma sırasında etkinleştirebilirsiniz: ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetActivateUI(true); ``` ## İsteğe bağlı kurulum \{#optional-setup\} ### Günlük Kaydı \{#logging\} #### Günlük kaydı sistemini kurma \{#set-up-the-logging-system\} Adapty, ne olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki düzeyler mevcuttur: | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Yalnızca hatalar loglanır | | `warn` | Kritik hatalara yol açmayan ancak dikkat edilmesi gereken SDK hataları ve mesajları loglanır | | `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır | | `verbose` | Hata ayıklama sırasında işe yarayabilecek her türlü ek bilgi (fonksiyon çağrıları, API sorguları vb.) loglanır | Adapty'yi yapılandırırken uygulamanızda log seviyesini ayarlayabilirsiniz: ```csharp showLineNumbers title="C#" // 'verbose' is recommended for development and the first production release var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY"); builder.LogLevel = AdaptyLogLevel.Verbose; ``` Log seviyesini çalışma zamanında da değiştirebilirsiniz: ```csharp showLineNumbers title="C#" Adapty.SetLogLevel(AdaptyLogLevel.Verbose, (error) => { // handle result }); ``` ### Veri politikaları \{#data-policies\} Adapty, açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz. Ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz. #### IP adresi toplama ve paylaşmayı devre dışı bırakma \{#disable-ip-address-collection-and-sharing\} Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `SetIPAddressCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi kullanıcı gizliliğini artırmak, bölgesel veri koruma düzenlemelerine (GDPR veya CCPA gibi) uymak ya da uygulamanız için IP tabanlı özellikler gerekli olmadığında gereksiz veri toplamayı azaltmak amacıyla kullanabilirsiniz. ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetIPAddressCollectionDisabled(true); ``` #### Reklam kimliği toplama ve paylaşımını devre dışı bırakma \{#disable-advertising-id-collection-and-sharing\} Adapty modülünü etkinleştirirken, reklam tanımlayıcılarının toplanmasını devre dışı bırakmak için `SetAppleIDFACollectionDisabled` ve/veya `SetGoogleAdvertisingIdCollectionDisabled` değerini `true` olarak ayarlayın. Varsayılan değer `false`'tur. Bu parametreyi; App Store/Google Play politikalarına uymak, App Tracking Transparency istemini tetiklemekten kaçınmak ya da uygulamanız reklam kimliklerine dayalı attribution veya analiz gerektirmiyorsa kullanın. ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAppleIDFACollectionDisabled(true) .SetGoogleAdvertisingIdCollectionDisabled(true); ``` #### AdaptyUI için medya önbelleği yapılandırmasını ayarlama \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI, varsayılan olarak performansı artırmak ve ağ kullanımını azaltmak için medyayı (resimler ve videolar gibi) önbelleğe alır. Özel bir yapılandırma sağlayarak önbellek ayarlarını özelleştirebilirsiniz. Varsayılan önbellek ayarlarını geçersiz kılmak için `SetAdaptyUIMediaCache` kullanın: ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAdaptyUIMediaCache( 100 * 1024 * 1024, // MemoryStorageTotalCostLimit 100MB null, // MemoryStorageCountLimit 100 * 1024 * 1024 // DiskStorageSizeLimit 100MB ); ``` Parametreler: | Parametre | Zorunlu | Açıklama | |-----------------------------|----------|-----------------------------------------------------------------------------------------------| | memoryStorageTotalCostLimit | isteğe bağlı | Bellekteki toplam önbellek boyutu (bayt cinsinden). Varsayılan değer platforma göre değişir. | | memoryStorageCountLimit | isteğe bağlı | Bellek depolamasının öğe sayısı sınırı. Varsayılan değer platforma göre değişir. | | diskStorageSizeLimit | isteğe bağlı | Diskteki dosya boyutu sınırı (bayt cinsinden). Varsayılan değer platforma göre değişir. | ### Yerel access level'ları etkinleştirin (Android) \{#enable-local-access-levels-android\} Varsayılan olarak [yerel access level'lar](local-access-levels) iOS'ta etkin, Android'de devre dışıdır. Android'de de etkinleştirmek için `SetGoogleLocalAccessLevelAllowed` değerini `true` olarak ayarlayın: ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetGoogleLocalAccessLevelAllowed(true); ``` ### Yedekten geri yüklemede veri temizleme \{#clear-data-on-backup-restore\} `SetAppleClearDataOnBackup` `true` olarak ayarlandığında, SDK uygulamanın iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywalllar dahil olmak üzere yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur. :::note Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır. ::: ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAppleClearDataOnBackup(true); ``` ## Sorun Giderme \{#troubleshooting\} #### Android yedekleme kuralları (Otomatik Yedekleme yapılandırması) \{#android-backup-rules-auto-backup-configuration\} Bazı SDK'lar (Adapty dahil) kendi Android Auto Backup yapılandırmasını içerir. Yedekleme kurallarını tanımlayan birden fazla SDK kullanıyorsanız, Android manifest birleştirme işlemi `android:fullBackupContent`, `android:dataExtractionRules` veya `android:allowBackup` ile ilgili bir hatayla başarısız olabilir. Tipik hata belirtileri: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note Bu değişiklikler Android platform dizininizde yapılmalıdır (genellikle projenizin `android/` klasöründe bulunur). ::: Sorunu çözmek için şunları yapmanız gerekir: - Manifest birleştirme işlemine, yedeklemeyle ilgili özellikler için uygulamanızın değerlerini kullanmasını söyleyin. - Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren yedekleme kuralı dosyaları oluşturun. #### 1. Manifestinize `tools` ad alanını ekleyin \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` dosyanızda, kök `<manifest>` etiketinin tools içerdiğinden emin olun: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` içinde yedekleme özelliklerini geçersiz kılın \{#2-override-backup-attributes-in-application\} Aynı `AndroidManifest.xml` dosyasında, `<application>` etiketini güncelleyerek uygulamanızın nihai değerleri sağlamasını ve manifest birleştirme işlemine kütüphane değerlerini değiştirmesini söyleyin: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` Herhangi bir SDK de `android:allowBackup` ayarlıyorsa, bunu `tools:replace` içine ekleyin: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Birleştirilmiş yedekleme kuralı dosyaları oluşturun \{#3-create-merged-backup-rules-files\} Android projenizin `res/xml/` dizininde, Adapty'nin kurallarını diğer SDK'ların kurallarıyla birleştiren XML dosyaları oluşturun. Android, işletim sistemi sürümüne bağlı olarak farklı yedekleme kuralı formatları kullandığından, her iki dosyayı da oluşturmak uygulamanızın desteklediği tüm Android sürümleriyle uyumluluk sağlar. :::note Aşağıdaki örneklerde örnek bir üçüncü taraf SDK olarak AppsFlyer kullanılmaktadır. Uygulamanızda kullandığınız diğer SDK'lar için kuralları değiştirin veya ekleyin. ::: **Android 12 ve üzeri için** (yeni veri çıkarma kuralları formatını kullanır): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11 ve altı için** (eski tam yedekleme içeriği formatını kullanır): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::important Unity'de bu değişiklikleri `Assets/Plugins/Android/AndroidManifest.xml` dosyasına uygulayın ve yedekleme kuralı dosyalarını `Assets/Plugins/Android/res/xml/` dizini altında oluşturun. ::: #### Android'de başka bir uygulamadan döndükten sonra satın almalar başarısız oluyor \{#purchases-fail-after-returning-from-another-app-in-android\} Satın alma akışını başlatan Activity, varsayılan dışı bir `launchMode` kullanıyorsa Android, kullanıcı Google Play'den, bir bankacılık uygulamasından veya tarayıcıdan geri döndüğünde bu Activity'yi hatalı biçimde yeniden oluşturabilir ya da yeniden kullanabilir. Bu durum satın alma sonucunun kaybolmasına veya iptal edilmiş olarak işlenmesine yol açabilir. Satın alma işlemlerinin doğru çalışması için, satın alma flow'unu başlatan Activity'de yalnızca `standard` veya `singleTop` başlatma modlarını kullanın; diğer modlardan kaçının. `AndroidManifest.xml` dosyanızda, satın alma flow'unu başlatan Activity'nin `standard` veya `singleTop` olarak ayarlandığından emin olun: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Paywall Android'de gösterildiğinde uygulama çöküyor \{#app-crashes-when-a-paywall-is-displayed-on-android\} Uygulamanız Android'de bir paywall görüntülenirken çöküyorsa, Kotlin eklentisi Gradle yapılandırmanızda eksik olabilir. Eklemek için: 1. **Player Settings** bölümünde, **Custom Launcher Gradle Template** ve **Custom Base Gradle Template** seçeneklerinin işaretlendiğinden emin olun. <img src="/assets/shared/img/kotlin-plugin1.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. `/Assets/Plugins/Android/launcherTemplate.gradle` dosyasına aşağıdaki satırı ekleyin: ```groovy showLineNumbers apply plugin: 'com.android.application' // highlight-next-line apply plugin: 'kotlin-android' apply from: 'setupSymbols.gradle' apply from: '../shared/keepUnitySymbols.gradle' ``` 3. Aşağıdaki satırı `/Assets/Plugins/Android/baseProjectTemplate.gradle` dosyasına ekleyin: ```groovy showLineNumbers plugins { // If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity // See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html // See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle // To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version id 'com.android.application' version '8.3.0' apply false id 'com.android.library' version '8.3.0' apply false // highlight-next-line id 'org.jetbrains.kotlin.android' version '1.8.0' apply false **BUILD_SCRIPT_DEPS** } ``` --- # File: unity-quickstart-paywalls --- --- title: "Unity SDK'da paywall'ları kullanarak satın almaları etkinleştirme" description: "Adapty SDK ile Unity uygulamanızda paywall'ları nasıl göstereceğinizi öğrenin." --- Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywall'lar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalardır. Adapty'de ürünleri almanın tek yolu paywall'lardır; bu tasarım sayesinde uygulama kodunuza dokunmadan teklifleri, fiyatlandırmayı ve ürün kombinasyonlarını değiştirebilirsiniz. - [**Placement'lar**](placements) – uygulamanızda paywall'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Kontrol panelinde placement'lar için paywall'lar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yapı, A/B testleri çalıştırmayı ve farklı kullanıcılara farklı paywall'lar göstermeyi kolaylaştırır. Adapty, uygulamanızda satın almaları etkinleştirmek için üç yöntem sunar. Uygulama gereksinimlerinize göre birini seçin: | Uygulama | Karmaşıklık | Ne zaman kullanılır | |------------------------------|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty Paywall Builder | ✅ Kolay | [No-code builder'da eksiksiz, satın almaya hazır bir paywall oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda halleder. | | Elle oluşturulan paywall'lar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda siz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için paywall nesnesini yine de Adapty'den alırsınız. [Kılavuza](unity-quickstart-manual) bakın. | | Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten var ve onu kullanmaya devam etmek istiyorsunuz. Observer modunun Adapty'de bazı sınırlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. | :::important **Aşağıdaki adımlar, Adapty paywall builder'da oluşturulan bir paywall'ın nasıl uygulanacağını göstermektedir.** Paywall builder'ı kullanmak istemiyorsanız [elle oluşturulan paywall'larda satın almaları yönetme kılavuzuna](unity-making-purchases) bakın. ::: Adapty paywall builder'da oluşturulmuş bir paywall'ı göstermek için uygulama kodunuzda yalnızca şunları yapmanız yeterlidir: 1. **Paywall'ı alın**: Paywall'ı Adapty'den alın. 2. **Paywall'ı gösterin, satın almaları Adapty halleder**: Uygulamanızda aldığınız paywall container'ını gösterin. 3. **Buton eylemlerini yönetin**: Kullanıcıların paywall ile etkileşimlerini uygulamanızın yanıtlarıyla ilişkilendirin. Örneğin, kullanıcılar butonlara tıkladığında bağlantılar açın veya paywall'ı kapatın. ## Başlamadan önce \{#before-you-start\} Başlamadan önce şu adımları tamamlayın: 1. Uygulamanızı Adapty Kontrol Paneli'nde [App Store](initial_ios) ve/veya [Google Play](initial-android)'e bağlayın. 2. Adapty'de [ürünlerinizi oluşturun](create-product). 3. [Bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 4. [Bir placement oluşturun ve paywall'ınızı ekleyin](create-placement). 5. Uygulama kodunuzda [Adapty SDK'yı yükleyin ve etkinleştirin](sdk-installation-unity). :::tip Bu adımları tamamlamanın en hızlı yolu [hızlı başlangıç kılavuzunu](quickstart) takip etmek ya da [Developer CLI](developer-cli-quickstart) kullanarak paywall'lar ve placement'lar oluşturmaktır. ::: ## 1. Paywall'ı alın \{#1-get-the-paywall\} Paywall'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilidir. Placement'lar, farklı kitleler için farklı paywall'lar çalıştırmanıza ya da [A/B testleri](ab-tests) yapmanıza olanak tanır. Adapty paywall builder'da oluşturulmuş bir paywall almak için şunları yapmanız gerekir: 1. `GetPaywall` metodunu kullanarak [placement](placements) ID'sine göre `paywall` nesnesini alın ve `HasViewConfiguration` özelliğini kontrol ederek builder'da oluşturulmuş bir paywall olup olmadığını doğrulayın. 2. `CreatePaywallView` metodunu kullanarak paywall görünümünü oluşturun. Görünüm, paywall'ı göstermek için gereken UI öğelerini ve stilleri içerir. :::important Görünüm yapılandırmasını alabilmek için Paywall Builder'da **Show on device** geçişini açmanız gerekir. Aksi takdirde boş bir görünüm yapılandırması alırsınız ve paywall gösterilmez. ::: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if(error != null) { // handle the error return; } // Create paywall view parameters var parameters = new AdaptyUICreatePaywallViewParameters(); // Create the paywall view AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if(error != null) { // handle the error return; } // view - the paywall view ready to be presented }); }); ``` :::info Bu hızlı başlangıç, bir paywall'ı göstermek için gereken minimum yapılandırmayı sağlar. Gelişmiş yapılandırma ayrıntıları için [paywall alma kılavuzumuza](unity-get-pb-paywalls) bakın. ::: ## 2. Paywall'ı gösterin \{#2-display-the-paywall\} Paywall yapılandırmasına sahip olduğunuzda, paywall'ınızı göstermek için birkaç satır kod eklemeniz yeterlidir. Paywall'ı göstermek için `CreatePaywallView` metoduyla oluşturulan `view` üzerinde `view.Present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar göstermeniz gerekiyorsa yeni bir `view` örneği oluşturmak için `CreatePaywallView`'u tekrar çağırın. ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::info Paywall'ın nasıl gösterileceğine dair daha fazla ayrıntı için [kılavuzumuza](unity-present-paywalls) bakın. ::: ## 3. Buton eylemlerini yönetin \{#3-handle-button-actions\} Kullanıcılar paywall'daki butonlara tıkladığında Unity SDK, satın almaları ve geri yüklemeleri otomatik olarak işler. Ancak diğer butonların özel veya önceden tanımlanmış ID'leri vardır ve kodunuzda eylem yönetimi gerektirir. Örneğin paywall'ınızda büyük olasılıkla bir kapat butonu ve açılacak URL'ler (kullanım koşulları ve gizlilik politikası gibi) bulunur. Bu eylemleri yönetmek için sınıfınızın `AdaptyPaywallsEventsListener` arayüzünü uygulaması ve bir dinleyici olarak kaydedilmesi gerekir. :::tip Buton [eylemlerini](unity-handle-paywall-actions) ve [olayları](unity-handling-events) nasıl yöneteceğinize dair kılavuzlarımızı okuyun. ::: ```csharp showLineNumbers title="Unity" public class YourClass : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { // Register this class as the paywall events listener Adapty.SetPaywallsEventsListener(this); } // AdaptyPaywallsEventsListener method - handles button actions public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; case AdaptyUIUserActionType.OpenUrl: Application.OpenURL(action.Value); break; default: break; } } } ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywall'ınız uygulamada gösterilmeye hazır. Paywall üzerinden bir test satın alması tamamlayabildiğinizden emin olmak için [App Store sandbox](test-purchases-in-sandbox) veya [Google Play Store](testing-on-android) üzerinde satın almalarınızı test edin. Artık doğru kullanıcılara paywall gösterdiğinizden veya ücretli özelliklere erişim verdiğinizden emin olmak için [kullanıcıların access level'ını kontrol etmeniz](unity-check-subscription-status) gerekir. ## Tam örnek \{#full-example\} Tüm bu adımların uygulamanızda birlikte nasıl entegre edilebileceğini aşağıda görebilirsiniz. ```csharp showLineNumbers using System; using UnityEngine; using AdaptySDK; public class PaywallManager : MonoBehaviour, AdaptyPaywallsEventsListener { [SerializeField] private string placementId = "YOUR_PLACEMENT_ID"; private AdaptyUIPaywallView currentPaywallView; void Start() { // Register for paywall events Adapty.SetPaywallsEventsListener(this); GetAndDisplayPaywall(); } private void GetAndDisplayPaywall() { Adapty.GetPaywall(placementId, (paywall, error) => { if (error != null) { Debug.LogError("Error getting paywall: " + error.Message); return; } if (paywall.HasViewConfiguration) { CreateAndPresentPaywallView(paywall); } else { Debug.LogWarning("Paywall was not created using the builder"); } }); } private void CreateAndPresentPaywallView(AdaptyPaywall paywall) { var parameters = new AdaptyUICreatePaywallViewParameters(); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if (error != null) { Debug.LogError("Error creating paywall view: " + error.Message); return; } currentPaywallView = view; view.Present((presentError) => { if (presentError != null) { Debug.LogError("Error presenting paywall: " + presentError.Message); return; } Debug.Log("Paywall presented successfully"); }); }); } // AdaptyPaywallsEventsListener implementation public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: Debug.Log("Close button pressed"); view.Dismiss(null); break; case AdaptyUIUserActionType.OpenUrl: Application.OpenURL(action.Value); break; default: break; } } // Required interface methods (implement as needed) public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } public void PaywallViewDidSelectProduct(AdaptyUIPaywallView view, string productId) { } public void PaywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } public void PaywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchasedResult) { } public void PaywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { } public void PaywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } public void PaywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } public void ShowPaywall() { GetAndDisplayPaywall(); } void OnDestroy() { if (currentPaywallView != null) { currentPaywallView.Dismiss(null); } } } ``` --- # File: unity-check-subscription-status --- --- title: "Unity SDK'da abonelik durumunu kontrol etme" description: "Adapty ile Unity uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin." --- Kullanıcıların ücretli içeriklere erişip erişemeyeceğine ya da bir paywall görmesi gerekip gerekmediğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir. Bu makalede, kullanıcılara paywall mı göstereceğinizi yoksa ücretli özelliklere erişim mi vereceğinizi belirlemek amacıyla profil durumuna nasıl erişeceğiniz anlatılmaktadır. ## Abonelik durumunu alma \{#get-subscription-status\} Bir kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken, profildeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var: - En güncel profil verilerine hemen ihtiyaç duyduğunuzda (örneğin uygulama başlangıcında) veya güncellemeyi zorlamak istediğinizde `GetProfile` çağırın. - Abonelik durumu her değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** ayarlayın. ### Profili alma \{#get-profile\} Abonelik durumunu almanın en kolay yolu, profile erişmek için `GetProfile` metodunu kullanmaktır: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access }); ``` ### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\} Uygulamanızda profil güncellemelerini otomatik olarak almak için: 1. `AdaptyEventListener` sınıfını genişletin ve `OnLoadLatestProfile` metodunu uygulayın. Adapty, kullanıcının abonelik durumu her değiştiğinde bu metodu otomatik olarak çağırır. 2. Bu metot çağrıldığında güncellenen profil verilerini saklayın; böylece ek ağ istekleri yapmadan uygulamanızın her yerinde kullanabilirsiniz. ```csharp public class SubscriptionManager : MonoBehaviour, AdaptyEventListener { private AdaptyProfile currentProfile; void Start() { // Register this object as an Adapty event listener Adapty.SetEventListener(this); } // Store the profile when it updates public void OnLoadLatestProfile(AdaptyProfile profile) { currentProfile = profile; // Update UI, unlock content, etc. } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } // Use stored profile instead of calling getProfile() public bool HasAccess() { if (currentProfile?.AccessLevels != null && currentProfile.AccessLevels.ContainsKey("premium")) { return currentProfile.AccessLevels["premium"].IsActive; } return false; } } ``` :::note Adapty, uygulamanız başladığında `OnLoadLatestProfile`'ı otomatik olarak çağırır; bu sayede cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verileri sağlanır. ::: ## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\} Paywall gösterme veya ücretli özelliklere erişim verme konusunda anlık kararlar almanız gerektiğinde, kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama başlangıcı, premium bölümlere girerken veya belirli içerikleri görüntülemeden önce gibi senaryolarda işe yarar. ```csharp private void CheckAccessLevel() { Adapty.GetProfile((profile, error) => { if (error != null) { Debug.LogError("Error checking access level: " + error.Message); // Show paywall if access check fails return; } var accessLevel = profile.AccessLevels["YOUR_ACCESS_LEVEL"]; if (accessLevel == null || !accessLevel.IsActive) { // Show paywall if no access } }); } private void InitializePaywall() { LoadPaywall(); CheckAccessLevel(); } ``` ## Sonraki adımlar \{#next-steps\} Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, kullanıcıların ödedikleri şeylere erişebildiğinden emin olmak için [kullanıcı profilleriyle çalışmayı](unity-quickstart-identify) öğrenin. --- # File: unity-quickstart-identify --- --- title: "Unity SDK'da kullanıcıları tanımlama" description: "Unity'de uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu." --- :::important Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa size yöneliktir. Burada, mevcut kimlik doğrulama sisteminizle uyumlu olacak şekilde Adapty'deki kullanıcı profilleriyle nasıl çalışacağınızı öğreneceksiniz. ::: Kullanıcıların satın almalarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır: - Uygulamanız arka uç kimlik doğrulaması kullanmıyorsa ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın. - Uygulamanızın arka uç kimlik doğrulaması varsa (veya olacaksa), [tanımlı kullanıcılar bölümüne](#identified-users) bakın. **Temel kavramlar**: - **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur. - Anonim **(customer user ID olmadan)** veya tanımlı **(customer user ID ile)** olabilirler. - Adapty'deki profilleri kendi dahili kimlik doğrulama sisteminizle çapraz referanslamak için **customer user ID** sağlarsınız. Anonim ve tanımlı kullanıcılar arasındaki farklar şunlardır: | | Anonim kullanıcılar | Tanımlı kullanıcılar | |-------------------------|-------------------------------------------------------|----------------------------------------------------------------------------------| | **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma | | **Profil yönetimi** | Her yeniden yüklemede yeni profil | Oturumlar ve cihazlar arasında aynı profil | | **Veri kalıcılığı** | Anonim kullanıcı verisi uygulama kurulumuna bağlıdır | Tanımlı kullanıcı verisi uygulama kurulumları arasında kalıcıdır | ## Anonim kullanıcılar \{#anonymous-users\} Arka uç kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı yönetmenize gerek yoktur**: 1. SDK, uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**. 2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profili ve mağaza hesabıyla ilişkilendirilir**. 3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihazdan** yüklediğinde, Adapty **etkinleştirmede yeni bir anonim profil oluşturur**. 4. Kullanıcı daha önce uygulamanızda satın alma yapmışsa, varsayılan olarak satın almalar SDK etkinleştirmesinde App Store'dan otomatik olarak senkronize edilir. Yani anonim kullanıcılarla her kurulumda yeni profil oluşturulur; ancak bu bir sorun değildir çünkü Adapty analizlerinde [yeni kurulum olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics). Anonim kullanıcılar için kurulumları **cihaz ID'lerine** göre saymanız gerekir. Bu durumda, yeniden yüklemeler dahil olmak üzere bir cihazdaki her uygulama kurulumu bir yükleme olarak sayılır. ## Tanımlı kullanıcılar \{#identified-users\} Uygulamadaki kullanıcıları tanımlamak için iki seçeneğiniz var: - [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğruladıklarında customer user ID ile `identify()` çağrısı yapın. - [**SDK etkinleştirmesi sırasında:**](#during-the-sdk-activation) Uygulama başlatılırken zaten bir customer user ID'niz varsa, `activate()` çağrısı yaparken bunu gönderin. :::important Varsayılan olarak, Adapty şu anda başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; yani her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Ayrıntılar için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın. ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Giriş/kayıt sırasında \{#during-loginsignup\} Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin, uygulamanıza giriş yaptıktan veya kaydolduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın. - Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty bunu otomatik olarak mevcut profille ilişkilendirir. - Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer. :::important Müşteri kullanıcı kimlikleri her kullanıcı için benzersiz olmalıdır. Parametre değerini sabit kodlarsanız, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir. ::: Diğer SDK metodlarını çağırmadan önce `Identify` tamamlanma callback'ini bekleyin. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar veya anonim profile düşer. Bkz. [Unity SDK'da çağrı sırası](unity-sdk-call-order). ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` ### SDK etkinleştirmesi sırasında \{#during-the-sdk-activation\} SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, ayrıca `identify` çağrısı yapmak yerine bunu `activate` metodunda gönderebilirsiniz. Customer user ID bilseniz de bunu yalnızca etkinleştirmeden sonra ayarlarsanız, etkinleştirmede Adapty yeni bir anonim profil oluşturur ve yalnızca `identify` çağrısı yaptıktan sonra mevcut profile geçer. Mevcut bir customer user ID (daha önce kullandığınız) veya yeni bir tane geçirebilirsiniz. Yeni bir tane geçirirseniz, etkinleştirmede oluşturulan yeni profil otomatik olarak customer user ID ile ilişkilendirilir. :::note Varsayılan olarak, anonim profil oluşturma analiz kontrol panellerini etkilemez; çünkü kurulumlar cihaz ID'lerine göre sayılır. Cihaz ID'si, bir cihazda mağazadan yapılan tek bir uygulama kurulumunu temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur. Bu, birinci veya tekrar kurulum olup olmadığına ya da mevcut bir customer user ID kullanılıp kullanılmadığına bağlı değildir. Profil oluşturma (SDK etkinleştirmesinde veya çıkışta), oturum açma veya uygulamayı yeniden yüklemeden yükseltme ek kurulum olayı oluşturmaz. Kurulumları cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidip [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın. ::: ```csharp showLineNumbers using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID"); // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` ### Kullanıcı çıkışı \{#log-users-out\} Kullanıcıların çıkış yapması için bir butonunuz varsa, `logout` metodunu kullanın. :::important Kullanıcı çıkışı, kullanıcı için yeni bir anonim profil oluşturur. ::: ```csharp showLineNumbers Adapty.Logout((error) => { if(error == null) { // successful logout } }); ``` :::info Kullanıcıları tekrar uygulamaya giriş yaptırmak için `identify` metodunu kullanın. ::: ### Girişsiz satın almalara izin verme \{#allow-purchases-without-login\} Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıktan sonra erişimlerini koruduğunuzdan emin olmanız gerekir: 1. Çıkış yapmış bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil ID'siyle ilişkilendirir. 2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlı profiliyle çalışmaya geçer. - Yeni bir customer user ID ise (örneğin, satın alma kayıt öncesinde yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur. - Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), profil geçişinden sonra gerçek access level'ı almanız gerekir. Tanımlamadan hemen sonra [`getProfile`](unity-check-subscription-status) çağrısı yapabilir veya veriler otomatik senkronize olması için [profil güncellemelerini dinleyebilirsiniz](unity-check-subscription-status). ## Sonraki adımlar \{#next-steps\} Tebrikler! Uygulamanızda uygulama içi ödeme mantığını hayata geçirdiniz! Uygulamanızın gelirini artırmanızı diliyoruz! Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz: - [**Test etme**](troubleshooting-test-purchases): Her şeyin beklendiği gibi çalıştığından emin olun - [**Onboardings**](onboardings): Onboarding'lerle kullanıcıları etkileyin ve elde tutmayı artırın - [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analiz hizmetleriyle entegre edin - [**Özel profil öznitelikleri ayarlama**](unity-setting-user-attributes): Kullanıcı profillerine özel öznitelikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz --- # File: adapty-sdk-integration-skill-unity --- --- title: "SDK entegrasyon skill'i ile Adapty'yi Unity uygulamanıza entegre edin" description: "Adapty SDK'yı AI kodlama aracınızla Unity uygulamanıza uçtan uca entegre etmek için adapty-sdk-integration skill'ini kullanın." --- [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. :::important Bu özellik beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, [adım adım entegrasyon kılavuzunu](adapty-cursor-unity) takip edin — AI aracınıza her aşamayı doğru belgelerle adım adım anlatır. ::: [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir. **Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır. **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez): ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz. Kurulumdan sonra skill'i projenizde çalıştırın: ``` /adapty-sdk-integration ``` Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir. --- # File: adapty-cursor-unity --- --- title: "Adapty'yi Unity uygulamanıza yapay zeka yardımıyla entegre edin" description: "Cursor, Context7, ChatGPT, Claude veya diğer yapay zeka araçlarını kullanarak Adapty'yi Unity uygulamanıza entegre etmek için adım adım kılavuz." --- Bu kılavuz, bir AI kodlama aracıyla Unity uygulamanıza Adapty'yi adım adım entegre etme sürecini anlatır — doğru Adapty dökümanlarını doğru sırayla besleyerek ilerlersiniz. For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\} Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı ayarların yapılmasını gerektirir. Bunu etkileşimli bir LLM aracıyla ya da Kontrol Paneli üzerinden manuel olarak yapabilirsiniz. ### Skill yaklaşımı (önerilen) \{#skill-approach-recommended\} Adapty CLI skill'i, LLM'inizin uygulamanızı, ürünlerinizi, access level'larınızı, paywall'larınızı ve placement'larınızı doğrudan kurmasını sağlar — her adım için kontrol panelini açmanıza gerek kalmaz. Yalnızca kontrol panelinde [mağazalarınızı bağlamanız](integrate-payments) yeterlidir. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Skill eklendikten sonra, agent'ınızda `/adapty-cli` komutunu çalıştırın. Mağazalarınızı bağlamak için kontrol panelini ne zaman açmanız gerektiği de dahil olmak üzere her adımda sizi yönlendirecektir. ### Kontrol paneli yaklaşımı \{#dashboard-approach\} Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, herhangi bir kod yazmadan önce bunlara ihtiyacınız olacak. LLM'niz kontrol paneli değerlerini sizin için arayamaz — bunları kendiniz sağlamanız gerekir. 1. **Uygulama mağazalarınızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** bölümüne gidin. Unity uygulamanız her iki platformu da hedefliyorsa hem App Store'u hem de Google Play'i bağlayın. Bu, satın alımların çalışması için gereklidir. [Uygulama mağazalarını bağlayın](integrate-payments) 2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin, ardından **API keys** bölümünü bulun. Kodda, bu Adapty yapılandırma builder'ına geçirdiğiniz string'dir. 3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere kodda doğrudan başvurmazsınız — Adapty bunları paywall'lar aracılığıyla iletir. [Ürün ekle](quickstart-products) 4. **Bir paywall ve placement oluşturun**: Adapty Kontrol Paneli'nde **Paywalls** sayfasında bir paywall oluşturun, ardından bunu **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `Adapty.GetPaywall("YOUR_PLACEMENT_ID")` çağrısına ilettiğiniz string'dir. [Paywall oluştur](quickstart-paywalls) 5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde, **Products** sayfasında ürün bazında yapılandırın. Kodda, `profile.AccessLevels["premium"]?.IsActive` içinde kontrol edilen string'dir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne göre farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kodlamaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product). :::tip Beşini de tamamladığınızda kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodunu üretebilir. ::: ### Hazır olduğunuzda kurulum \{#set-up-when-ready\} Bunlar kodlamaya başlamak için zorunlu değildir, ancak entegrasyonunuz olgunlaştıkça bunlara ihtiyaç duyacaksınız: - **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez. [A/B testleri](ab-tests) - **Ek paywall'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `GetPaywall` çağrısı ekleyin. - **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration). ## LLM'inize Adapty Dokümanlarını Besleyin \{#feed-adapty-docs-to-your-llm\} ### Context7'yi Kullanın (önerilen) [Context7](https://context7.com), LLM'inizin güncel Adapty belgelerine doğrudan erişmesini sağlayan bir MCP sunucusudur. LLM, ne sorduğunuza göre doğru belgeleri otomatik olarak getirir — manuel URL yapıştırmaya gerek yoktur. Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurulum için şunu çalıştırın: ``` npx ctx7 setup ``` Bu komut, editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın. Yapılandırıldıktan sonra, Adapty kütüphanesine prompt'larınızda referans verin: ``` Use the adaptyteam/adapty-docs library to look up how to install the Unity SDK ``` :::warning Context7, belge bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin doğru çalıştığından emin olmak için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin. ::: ### Düz metin dokümanları kullanın \{#use-plain-text-docs\} Her Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** butonuna tıklayın. Örneğin: [adapty-cursor-unity.md](https://adapty.io/docs/tr/adapty-cursor-unity.md). Aşağıdaki [uygulama adım adım rehberi](#implementation-walkthrough)'nin her aşamasında, yapıştırabileceğiniz `.md` bağlantılarıyla birlikte "Send this to your LLM" bloğu yer almaktadır. Aynı anda daha fazla doküman için aşağıdaki [indeks dosyaları ve platforma özel alt kümelerine](#plain-text-doc-index-files) bakın. ## Uygulama adım adım \{#implementation-walkthrough\} Bu kılavuzun geri kalanı, Adapty entegrasyonunu uygulama sırasına göre ele alır. Her aşamada LLM'inize gönderebileceğiniz dokümanlar, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar yer alır. ### Entegrasyonunuzu Planlayın \{#plan-your-integration\} Koda geçmeden önce, LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor'ın veya Claude Code'un plan modu gibi), LLM'in herhangi bir kod yazmadan önce hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bunu kullanın. LLM'inize satın alma işlemleri için hangi yaklaşımı kullandığınızı söyleyin — bu, takip etmesi gereken kılavuzları etkiler: - [**Adapty Paywall Builder**](adapty-paywall-builder): Adapty'nin no-code builder'ında paywall'lar oluşturursunuz ve SDK bunları otomatik olarak render eder. - [**Manuel oluşturulan paywall'lar**](unity-making-purchases): Kendi paywall arayüzünüzü kodla oluşturursunuz ancak ürünleri çekmek ve satın almaları yönetmek için Adapty'yi kullanmaya devam edersiniz. - [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız. Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](unity-quickstart-paywalls) okuyun. ### SDK'yı Yükleyin ve Yapılandırın \{#install-and-configure-the-sdk\} Adapty SDK paketini Unity Package Manager aracılığıyla ekleyin ve Public SDK anahtarınızla etkinleştirin. Bu, temel adımdır — diğer hiçbir şey bu olmadan çalışmaz. **Rehber:** [Adapty SDK'yı yükleyin ve yapılandırın](sdk-installation-unity) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/sdk-installation-unity.md ``` :::tip[Checkpoint] - **Beklenen:** Proje derleniyor ve çalışıyor. Unity Console, Adapty aktivasyon logunu gösteriyor. - **Dikkat:** "Public API key is missing" → **App settings** bölümünden gerçek anahtarınızı kopyalayıp placeholder'ın yerine yapıştırdığınızı kontrol edin. ::: ### Paywall'ları göster ve satın almaları yönet \{#show-paywalls-and-handle-purchases\} Placement ID'sine göre bir paywall getir, görüntüle ve satın alma olaylarını yönet. İhtiyacınız olan kılavuzlar, satın almaları nasıl yönettiğinize bağlıdır. Her satın almayı ilerledikçe sandbox'ta test et — sona kadar bekleme. Kurulum talimatları için [Sandbox'ta satın alma testi](test-purchases-in-sandbox) bölümüne bakın. <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **Kılavuzlar:** - [Paywall'ları kullanarak satın alımları etkinleştirme (hızlı başlangıç)](unity-quickstart-paywalls) - [Paywall Builder paywall'larını ve yapılandırmalarını getirme](unity-get-pb-paywalls) - [Paywall'ları görüntüleme](unity-present-paywalls) - [Paywall olaylarını yönetme](unity-handling-events) - [Buton eylemlerine yanıt verme](unity-handle-paywall-actions) Bu bir çeviri görevi değil — bu, bir LLM'e kod yazmadan önce okuması gereken Adapty dokümanlarının bağlantılarını içeren bir komuttur. Bu mesajı olduğu gibi LLM'inize gönderin: --- Read these Adapty docs before writing code: - https://adapty.io/docs/tr/unity-quickstart-paywalls.md - https://adapty.io/docs/tr/unity-get-pb-paywalls.md - https://adapty.io/docs/tr/unity-present-paywalls.md - https://adapty.io/docs/tr/unity-handling-events.md - https://adapty.io/docs/tr/unity-handle-paywall-actions.md :::tip[Checkpoint] - **Beklenen:** Paywall, yapılandırdığınız ürünlerle görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikler. - **Dikkat:** Boş paywall veya `GetPaywall` hatası → placement ID'nin kontrol paneliyle tam olarak eşleştiğini ve placement'a bir kitle atandığını doğrulayın. ::: </TabItem> <TabItem value="manual" label="Manuel paywall'lar"> **Kılavuzlar:** - [Özel paywall'ınızda satın almaları etkinleştirin (hızlı başlangıç)](unity-quickstart-manual) - [Paywall'ları ve ürünleri getirin](fetch-paywalls-and-products-unity) - [Remote config ile tasarlanan paywall'ı render edin](present-remote-config-paywalls-unity) - [Satın alma yapın](unity-making-purchases) - [Satın almaları geri yükleyin](unity-restore-purchase) Bu mesajı LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/unity-quickstart-manual.md - https://adapty.io/docs/tr/fetch-paywalls-and-products-unity.md - https://adapty.io/docs/tr/present-remote-config-paywalls-unity.md - https://adapty.io/docs/tr/unity-making-purchases.md - https://adapty.io/docs/tr/unity-restore-purchase.md ``` :::tip[Checkpoint] - **Beklenen:** Özel paywall'ınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikliyor. - **Yaygın sorun:** Boş ürün dizisi → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitleye sahip olduğunu doğrulayın. ::: </TabItem> <TabItem value="observer" label="Observer mode"> **Kılavuzlar:** - [Observer mode'a genel bakış](observer-vs-full-mode) - [Observer mode'u uygulama](implement-observer-mode-unity) - [Observer mode'da işlemleri raporlama](report-transactions-observer-mode-unity) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/observer-vs-full-mode.md - https://adapty.io/docs/tr/implement-observer-mode-unity.md - https://adapty.io/docs/tr/report-transactions-observer-mode-unity.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Mevcut satın alma akışınızı kullanarak yaptığınız sandbox satın alımından sonra işlem, Adapty kontrol panelindeki **Event Feed** bölümünde görünür. - **Dikkat:** Hiç event gelmiyorsa → işlemleri Adapty'ye raporladığınızı ve her iki mağaza için sunucu bildirimlerinin yapılandırıldığını doğrulayın. ::: </TabItem> </Tabs> ### Abonelik durumunu kontrol et \{#check-subscription-status\} Satın alma işleminin ardından, premium içeriğe erişimi kısıtlamak için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin. **Rehber:** [Abonelik durumunu kontrol et](unity-check-subscription-status) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/unity-check-subscription-status.md ``` :::tip[Kontrol Noktası] - **Beklenen:** Sandbox satın almasının ardından `profile.AccessLevels["premium"]?.IsActive` değeri `true` döner. - **Dikkat:** Satın almadan sonra `AccessLevels` boş geliyor → ürüne kontrol panelinde bir access level atanıp atanmadığını kontrol edin. ::: ### Kullanıcıları tanımlayın \{#identify-users\} Uygulama kullanıcı hesaplarını Adapty profilleriyle ilişkilendirerek satın almaların cihazlar arasında kalıcı olmasını sağlayın. :::important Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın. ::: **Kılavuz:** [Kullanıcıları tanımlayın](unity-quickstart-identify) Bunu LLM'inize gönderin: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/tr/unity-quickstart-identify.md ``` :::tip[Checkpoint] - **Beklenen:** `Adapty.Identify("your-user-id")` çağrısının ardından, kontrol panelindeki **Profiles** bölümünde özel kullanıcı kimliğiniz görünür. - **Dikkat:** Anonim profil attributionunu önlemek için `Identify`'ı aktivasyondan sonra, paywall'ları çekmeden önce çağırın. ::: ### Yayına hazırlanın \{#prepare-for-release\} Entegrasyonunuz sandbox ortamında çalışır hale geldiğinde, her şeyin production'a hazır olduğundan emin olmak için yayın kontrol listesini gözden geçirin. **Rehber:** [Yayın kontrol listesi](release-checklist) Bunu LLM'inize gönderin: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/tr/release-checklist.md ``` :::tip[Checkpoint] - **Beklenen:** Tüm kontrol listesi öğeleri onaylandı: mağaza bağlantıları, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri. - **Dikkat:** Eksik sunucu bildirimleri → App Store Sunucu Bildirimlerini **App settings → iOS SDK** bölümünde, Google Play Gerçek Zamanlı Geliştirici Bildirimlerini ise **App settings → Android SDK** bölümünde yapılandırın. ::: ## Düz metin belge dizin dosyaları \{#plain-text-doc-index-files\} LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam sağlamanız gerekiyorsa, tüm Adapty belgelerini listeleyen veya birleştiren dizin dosyaları sunuyoruz: - [`llms.txt`](https://adapty.io/docs/tr/llms.txt): Tüm sayfaları `.md` bağlantılarıyla listeler. LLM'lerin web sitelerine erişimini kolaylaştırmak için kullanılan [gelişmekte olan bir standart](https://llmstxt.org/). Bazı yapay zeka ajanlarında (ör. ChatGPT) `llms.txt` dosyasını indirip sohbete yüklemeniz gerekebilir. - [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesini tek bir dosyada birleştirir. Çok büyük bir dosya; yalnızca tam resme ihtiyaç duyduğunuzda kullanın. - Unity'e özel [`unity-llms.txt`](https://adapty.io/docs/tr/unity-llms.txt) ve [`unity-llms-full.txt`](https://adapty.io/docs/tr/unity-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler. --- # File: unity-get-pb-paywalls --- --- title: "Unity SDK'da Paywall Builder paywalllerini ve konfigürasyonlarını getirme" description: "Adapty'de Unity uygulamanızda daha iyi abonelik kontrolü için PB paywalllerini nasıl alacağınızı öğrenin." --- [Adapty Kontrol Paneli'nde yeni Paywall Builder ile paywall'unuzun görsel kısmını tasarladıktan](adapty-paywall-builder) sonra, bunu mobil uygulamanızda gösterebilirsiniz. Bu süreçteki ilk adım, placement ile ilişkili paywall'u ve görünüm yapılandırmasını aşağıda açıklandığı gibi almaktır. :::warning Yeni Paywall Builder, Unity SDK sürüm 3.3.0 veya üzeriyle çalışır. ::: Lütfen bu konunun Paywall Builder ile özelleştirilmiş paywallları kapsadığını unutmayın. Eğer paywalllarınızı manuel olarak uyguluyorsanız, lütfen [Uzak config paywalllar için paywall ve ürünleri mobil uygulamanızda getirme](fetch-paywalls-and-products-unity) konusuna bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywallları görüntülemeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK](sdk-installation-unity) kurun. </details> ## Paywall Builder ile tasarlanan paywall'u getirme \{#fetch-paywall-designed-with-paywall-builder\} [Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem gösterilecek içeriği hem de nasıl gösterileceğini barındırır. Yine de placement aracılığıyla ID'sini, view konfigürasyonunu almanız ve ardından mobil uygulamanızda sunmanız gerekir. En iyi performansı sağlamak için, paywall'ı ve [görünüm yapılandırmasını](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) olabildiğince erken almanız, böylece kullanıcıya sunulmadan önce görsellerin indirilmesi için yeterli süre tanımanız kritik önem taşır. Bir paywall almak için `GetPaywall` metodunu kullanın: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi ise bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.</p><p>Yerel ayar kodları ve bunların nasıl kullanılmasını önerdiğimiz hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, mevcut olması halinde önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri deneyimler. Önbellek düzenli aralıklarla güncellenir, dolayısıyla ağ isteklerini azaltmak amacıyla oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını; yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Paywall'ları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman paywall'larınızın en güncel sürümünü almanızı garantilemek için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün kimliklerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer birçok özelliği içeren bir [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesi. | ## Paywall Builder ile tasarlanan paywall'un görünüm yapılandırmasını getirin \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Paywall Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse görünüm yapılandırması getirilemez. ::: Paywall'u getirdikten sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir `ViewConfiguration` içerip içermediğini kontrol edin. Bu bilgi, paywall'u nasıl görüntüleyeceğinizi belirler. `ViewConfiguration` mevcutsa Paywall Builder paywall'u olarak ele alın; yoksa [remote config paywall olarak işleyin](present-remote-config-paywalls-unity). Unity SDK'da, görünüm yapılandırmasını manuel olarak önceden getirmeye gerek kalmadan doğrudan `CreatePaywallView` metodunu çağırın. :::warning `CreatePaywallView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `CreatePaywallView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```csharp showLineNumbers var parameters = new AdaptyUICreatePaywallViewParameters() .SetPreloadProducts(preloadProducts) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | :------------------ | :------------- | :----------------------------------------------------------- | | **paywall** | zorunlu | İstenen paywall için bir controller edinmek amacıyla kullanılan `AdaptyPaywall` nesnesi. | | **loadTimeout** | varsayılan: 5 sn | Bu yöntem için zaman aşımı sınırını belirler. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür. Arka planda farklı isteklerden oluşabileceğinden, bu yöntem nadir durumlarda `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir. | | **PreloadProducts** | isteğe bağlı | Ekranda ürünlerin görüntülenme süresini optimize etmek için bir `AdaptyPaywallProducts` dizisi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. | | **CustomTags** | isteğe bağlı | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlayın. Özel etiketler, paywall içeriğinde yer tutucu olarak işlev görür; paywall içinde kişiselleştirilmiş içerik sunmak için belirli dizelerle dinamik olarak değiştirilirler. Daha fazla ayrıntı için Paywall Builder'da özel etiketler konusuna bakın. | | **CustomTimers** | isteğe bağlı | Özel zamanlayıcıların ve bitiş tarihlerinin bir sözlüğünü tanımlayın. Özel zamanlayıcılar, paywallınızda geri sayım sayaçları görüntülemenizi sağlar. | :::note Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesi eklemeyi](add-paywall-locale-in-adapty-paywall-builder) ve yerel ayar kodlarını doğru kullanmayı [buradan](localizations-and-locale-codes) öğrenebilirsiniz. ::: Görünümü elde ettikten sonra, [paywallı gösterin](unity-present-paywalls). ## Varlıkları özelleştirme \{#customize-assets\} Paywallınızdaki görüntü ve videoları özelleştirmek için özel varlıkları uygulayın. Hero görüntü ve videoların önceden tanımlanmış ID'leri vardır: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefleyerek davranışlarını özelleştirirsiniz. Diğer görüntü ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir. Örneğin şunları yapabilirsiniz: - Bazı kullanıcılara farklı bir görüntü veya video gösterin. - Uzaktaki ana görüntü yüklenirken yerel bir önizleme görüntüsü gösterin. - Video başlamadan önce bir önizleme görüntüsü gösterin. :::important Bu özelliği kullanmak için Adapty Unity SDK'yı 3.8.0 veya üzeri bir sürüme güncelleyin. ::: Aşağıda, basit bir sözlük aracılığıyla özel varlıkları nasıl sağlayabileceğinize dair bir örnek bulunmaktadır: ```csharp showLineNumbers var customAssets = new Dictionary<string, AdaptyCustomAsset> { { "custom_image", AdaptyCustomAsset.LocalImageFile("custom_assets/images/custom_image.png") }, { "hero_video", AdaptyCustomAsset.LocalVideoFile("custom_assets/videos/custom_video.mp4") } }; var parameters = new AdaptyUICreatePaywallViewParameters() .SetCustomAssets(customAssets) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // sonucu işle }); ``` :::note Bir asset bulunamazsa, paywall varsayılan görünümüne geri döner. ::: ## Unity uygulamanızda geliştirici tanımlı zamanlayıcılar kurma \{#set-up-developer-defined-timers\} Unity uygulamanızda özel zamanlayıcılar kullanmak için, zamanlayıcı ID'leri ve bitiş tarihlerinden oluşan bir sözlüğü doğrudan `SetCustomTimers` metoduna geçirebilirsiniz. İşte bir örnek: ```csharp showLineNumbers var customTimers = new Dictionary<string, DateTime> { { "CUSTOM_TIMER_6H", DateTime.Now.AddHours(6) }, { "CUSTOM_TIMER_NY", new DateTime(2025, 1, 1) } }; var parameters = new AdaptyUICreatePaywallViewParameters() .SetCustomTimers(customTimers) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. Zamanlayıcı çözümleyici, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin: - `CUSTOM_TIMER_NY`: Yılbaşı gibi zamanlayıcının bitiş anına kalan süre. - `CUSTOM_TIMER_6H`: Kullanıcının paywall'ı açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman. ## Varsayılan kitle paywallı ile paywall getirme işlemini hızlandırın \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında getirilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir paywallın getirilmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu çözmek için, belirtilen placement'ın **All Users** kitlesine ait paywallını getiren `GetPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın [Paywall Getirme](#fetch-paywall) bölümünde açıklandığı gibi `getPaywall` metoduyla paywall getirmek olduğunu anlamak çok önemlidir. :::warning `GetPaywallForDefaultAudience` yerine `GetPaywall` kullanmayı tercih edin; çünkü ikincisinin önemli kısıtlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorun çıkarabilir; ya geriye dönük uyumlu tasarımlar gerektirir ya da eski sürümlerin yanlış görüntülenebileceğini kabul etmeniz gerekir. - **Kişiselleştirme yok**: Yalnızca "Tüm Kullanıcılar" kitlesi için içerik gösterir; ülke, attribution veya özel niteliklere dayalı hedefleme yapılamaz. Bu dezavantajlara karşın daha hızlı veri çekme kullanım durumunuz için daha önemliyse, aşağıda gösterildiği gibi `GetPaywallForDefaultAudience` kullanın. Aksi takdirde, [yukarıda](#fetch-paywall) açıklandığı şekilde `GetPaywall` kullanın. ::: ```csharp showLineNumbers Adapty.GetPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Paywall yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere erişmesini sağladığı için bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel verilere her zaman ulaşamayabilir; ancak internet bağlantısı ne kadar düzensiz olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle oturum sırasında ağ isteklerini önlemek amacıyla kullanmak güvenlidir.</p><p></p><p>Önbelleğin, uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırıldığında veya manuel temizleme yapıldığında temizlendiğini unutmayın.</p><p></p><p>Adapty SDK, paywall'ları yerel olarak iki katmanda depolar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek paywall'lar. Paywall'ları daha hızlı yüklemek için CDN, CDN'e erişilemediği durumlar için ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywall'larınızın her zaman en güncel sürümünü almanızı garantilemek için tasarlanmıştır.</p> | --- # File: unity-present-paywalls --- --- title: "Paywallları görüntüleme" description: "Adapty SDK ile Unity uygulamanızda paywallları nasıl görüntüleyeceğinizi öğrenin." --- Paywall Builder ile bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir. :::warning Bu kılavuz, Adapty SDK 3.3.0 veya sonrasını gerektiren **yeni Paywall Builder**'ı kapsamaktadır. Remote config paywalllarını sunmak için bkz. [Remote config ile tasarlanan paywallları render etme](present-remote-config-paywalls). ::: Bir paywall görüntülemek için, [`CreatePaywallView`](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) metodu tarafından oluşturulan `view` üzerinde `view.Present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar görüntülemeniz gerekiyorsa, yeni bir `view` örneği oluşturmak için `CreatePaywallView`'ı bir kez daha çağırın. :::warning Aynı `view`'ı yeniden oluşturmadan tekrar kullanmak, `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Diyalog gösterme \{#show-dialog\} Android'de bir paywall görünümü sunulduğunda, yerel uyarı iletişim kutuları yerine bu metodu kullanın. Android'de normal uyarılar paywall görünümünün arkasında kalarak kullanıcılara görünmez hale gelir. Bu metod, tüm platformlarda iletişim kutusunun paywall'ın üzerinde düzgün şekilde gösterilmesini sağlar. ```csharp showLineNumbers title="Unity" var dialog = new AdaptyUIDialogConfiguration() .SetTitle("Close paywall?") .SetContent("You will lose access to exclusive offers.") .SetDefaultActionTitle("Stay") .SetSecondaryActionTitle("Close"); AdaptyUI.ShowDialog(view, dialog, (action, error) => { if (error == null) { if (action == AdaptyUIDialogActionType.Secondary) { // User confirmed - close the paywall view.Dismiss(); } // If primary - do nothing, user stays } }); ``` ## iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `Present()` metoduna `iosPresentationStyle` parametresini geçirerek paywall'ın iOS'ta nasıl sunulacağını yapılandırın. Parametre, `AdaptyUIIOSPresentationStyle.FullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.PageSheet` değerlerini kabul eder. ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` --- # File: unity-handle-paywall-actions --- --- title: "Unity SDK'da düğme eylemlerine yanıt verme" description: "Daha iyi uygulama monetizasyonu için Unity'de Adapty kullanarak paywall düğme eylemlerini yönetin." --- Adapty Paywall Builder kullanarak paywall oluşturuyorsanız, düğmeleri doğru şekilde yapılandırmanız gerekir: 1. [Paywall builder'da bir düğme ekleyin](paywall-buttons) ve bu düğmeye mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun. 2. Uygulamanızın kodunda, atadığınız her eylemi işleyecek kodu yazın. Bu rehber, özel ve hazır eylemleri kodunuzda nasıl yöneteceğinizi göstermektedir. :::warning **Yalnızca satın almalar ve geri yüklemeler otomatik olarak işlenir.** Paywallları kapatma veya bağlantı açma gibi diğer tüm düğme eylemleri için uygulama kodunuzda ilgili işleyicileri uygulamanız gerekir. ::: ## Paywallları kapatma \{#close-paywalls\} Paywall'ınızı kapatacak bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve **Close** eylemini atayın. 2. Uygulama kodunuzda, paywall'ı kapatan `close` eylemi için bir işleyici uygulayın. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; default: // handle other events break; } } ``` ## Paywall'lardan URL açma \{#open-urls-from-paywalls\} :::tip Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemine sahip düğmelerle aynı şekilde işleyin. ::: Paywall'ınızdan bir bağlantı açan bir düğme eklemek için (örneğin, **Kullanım Koşulları** veya **Gizlilik Politikası**): 1. Paywall builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin. 2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if(!string.IsNullOrWhiteSpace(urlString)) { Application.OpenURL(urlString); } break; default: // handle other events break; } } ``` ## Uygulamaya giriş yapma \{#log-into-the-app\} Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin ve `login` ID'siyle **Custom** eylemini atayın. 2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` özel eylemi için bir işleyici uygulayın. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "login") { // Navigate to login scene SceneManager.LoadScene("LoginScene"); } break; default: // handle other events break; } } ``` ## Özel eylemleri yönetme \{#handle-custom-actions\} Diğer eylemleri yöneten bir düğme eklemek için: 1. Paywall builder'da bir düğme ekleyin, **Custom** eylemini atayın ve bir ID belirleyin. 2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın. Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa, başka bir paywall görüntüleyen bir düğme ekleyebilirsiniz: ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "openNewPaywall") { // Display another paywall ShowAlternativePaywall(); } break; default: // handle other events break; } } private void ShowAlternativePaywall() { // Implement your logic to show alternative paywall } ``` --- # File: unity-handling-events --- --- title: "Paywall olaylarını yönet" description: "Adapty SDK ile Unity uygulamanızda paywall olaylarını nasıl yöneteceğinizi öğrenin." --- :::important Bu rehber; satın alma, geri yükleme, ürün seçimi ve paywall render işlemlerine ait olay yönetimini kapsar. Ayrıca buton işlemlerini de (paywallı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton aksiyonlarını yönetme rehberimize](unity-handle-paywall-actions) bakın. ::: [Paywall Builder](adapty-paywall-builder) ile yapılandırılan paywall'lar, satın alma ve geri yükleme işlemleri için ek kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; buton tıklamaları (kapat butonları, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili aksiyonlara dair bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. :::warning Bu rehber yalnızca Adapty SDK v3.3.0 veya üzerini gerektiren **yeni Paywall Builder paywall'ları** içindir. ::: :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Olayları yönetme \{#handling-events\} Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyPaywallsEventsListener` arayüzünü uygulayın: ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { Adapty.SetPaywallsEventsListener(this); } // Implement all required interface methods below } ``` ### Kullanıcı kaynaklı olaylar \{#user-generated-events\} #### Paywall göründü \{#paywall-appeared\} Paywall görünümü ekranda gösterildiğinde tetiklenir. :::note iOS'ta, kullanıcı bir paywall içindeki [web paywall butonuna](web-paywall#step-2a-add-a-web-purchase-button) dokunduğunda ve uygulama içi tarayıcıda bir web paywall açıldığında da tetiklenir. ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### Paywall kayboldu \{#paywall-disappeared\} Paywall görünümü ekrandan kapatıldığında tetiklenir. :::note iOS'ta, bir paywalldan uygulama içi tarayıcıda açılan [web paywall](web-paywall#step-2a-add-a-web-purchase-button) ekrandan kaybolduğunda da tetiklenir. ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### Ürün seçimi \{#product-selection\} Kullanıcı ya da sistem tarafından satın alma için bir ürün seçildiğinde tetiklenir. ```csharp showLineNumbers title="Unity" public void PaywallViewDidSelectProduct( AdaptyUIPaywallView view, string productId ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> #### Satın alma başladı \{#started-purchase\} Kullanıcı satın alma sürecini başlattığında tetiklenir. ```csharp showLineNumbers title="Unity" public void PaywallViewDidStartPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### Başarılı, iptal edilmiş veya beklemedeki satın alma \{#successful-canceled-or-pending-purchase\} Satın alma başarılı olursa, kullanıcı iptal ederse veya satın alma beklemede kalırsa bu metod tetiklenir. Kullanıcı iptalleri ve beklemedeki ödemeler (örn. ebeveyn onayı gerekli) `PaywallViewDidFailPurchase` yerine bu metodu tetikler. ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchasedResult ) { } ``` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCancelled" } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } ``` </Details> Bu durumda ekranı kapatmanızı öneririz. #### Başarısız satın alma \{#failed-purchase\} Bir hata nedeniyle satın alma başarısız olursa bu metod tetiklenir. StoreKit/Google Play Billing hataları (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hataları ve sistem hataları buna dahildir. Kullanıcı iptallerinin iptal sonucuyla `PaywallViewDidFinishPurchase`'i, beklemedeki ödemelerin ise bu metodu tetiklemediğini unutmayın. ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> #### Geri yükleme başladı \{#started-restore\} Kullanıcı geri yükleme sürecini başlattığında tetiklenir: ```csharp showLineNumbers title="Unity" public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### Başarılı geri yükleme \{#successful-restore\} Satın alma geri yüklemesi başarılı olduğunda tetiklenir: ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishRestore( AdaptyUIPaywallView view, AdaptyProfile profile ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Bunu nasıl kontrol edeceğinizi öğrenmek için [Abonelik durumu](unity-listen-subscription-changes) konusuna bakın. #### Başarısız geri yükleme \{#failed-restore\} Satın alma geri yüklemesi başarısız olduğunda tetiklenir: ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailRestore( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> #### Web ödeme navigasyonu tamamlandı \{#finished-web-payment-navigation\} Satın alma için bir [web paywall](web-paywall) açılmaya çalışıldıktan sonra (başarılı ya da başarısız), bu metod tetiklenir: ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishWebPaymentNavigation( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error ) { } ``` **Parametreler:** - `product`: Web paywallın açıldığı (veya açılmaya çalışıldığı) ürün - `error`: Web paywall başarıyla açıldıysa `null`, başarısız olduysa bir `AdaptyError` <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "wrong_param", "message": "Current method is not available for this product", "details": { "underlyingError": "Product not configured for web purchases" } } } ``` </Details> ### Veri çekme ve render işlemleri \{#data-fetching-and-rendering\} #### Ürün yükleme hataları \{#product-loading-errors\} Ürün yükleme başarısız olduğunda tetiklenir ve `AdaptyError` döndürür. Başlatma sırasında ürün dizisini geçmediyseniz AdaptyUI gerekli nesneleri sunucudan kendi alır. Bu işlem başarısız olabilir; AdaptyUI hatayı bu metodu çağırarak bildirir: ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailLoadingProducts( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> #### Render hataları \{#rendering-errors\} Arayüz render sırasında bir hata oluştuğunda tetiklenir ve `AdaptyError` döndürür: ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailRendering( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> Normal koşullarda bu tür hatalar yaşanmamalıdır; böyle bir hatayla karşılaşırsanız lütfen bize bildirin. --- # File: unity-web-paywalls --- --- title: "Unity SDK'da web paywall'ları uygulayın" description: "App Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall'ı kurun." --- :::important Başlamadan önce, [kontrol panelinde web paywall'ınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK sürüm 3.14 veya daha yenisini yüklediğinizden emin olun. ::: ## Web paywall'ları açın \{#open-web-paywalls\} Kendiniz geliştirdiğiniz bir paywall üzerinde çalışıyorsanız, web paywall'larını SDK metodu aracılığıyla yönetmeniz gerekir. `Adapty.OpenWebPaywall` metodu: 1. Adapty'nin belirli bir kullanıcıya gösterilen paywall'ı yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur. 2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü takip eder ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `Adapty.GetProfile` isteği gönderir. Bu sayede ödeme başarılı olmuşsa ve erişim hakları güncellenmiş ise abonelik uygulamada neredeyse anında etkinleşir. ```csharp showLineNumbers title="Unity" Adapty.OpenWebPaywall( product, (error) => { if (error != null) { Debug.LogError($"Failed to open web paywall: {error.Message}"); } else { Debug.Log("Web paywall opened successfully"); } } ); ``` :::note `OpenWebPaywall` metodunun iki sürümü vardır: 1. `OpenWebPaywall(product)`: URL'leri paywall'a göre oluşturur ve ürün verilerini de URL'lere ekler. 2. `OpenWebPaywall(paywall)`: URL'leri paywall'a göre oluşturur; ürün verilerini URL'lere eklemez. Adapty paywall'ındaki ürünler web paywall'ındaki ürünlerden farklıysa bunu kullanın. ::: #### Hataları yönetin \{#handle-errors\} | Hata Kodu | Açıklama | Önerilen İşlem | |-----------|----------|----------------| | `AdaptyErrorCode.WrongParam` | Paywall veya ürünün yapılandırılmış bir web satın alma URL'si yok ya da URL tarayıcıda açılamadı | Ayrıntılar için hata mesajını kontrol edin. Adapty Kontrol Paneli'nde paywall/ürün yapılandırmasını doğrulayın veya cihaz ayarlarını kontrol edin. | | `AdaptyErrorCode.DecodingFailed` | URL'deki parametreler düzgün şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimlendirilmiş olduğunu doğrulayın | :::note Neyin yanlış gittiğine dair ayrıntılı bilgi almak için hatanın `Message` özelliğini kontrol edin; `WrongParam` birden fazla soruna işaret edebilir (eksik satın alma URL'si, tarayıcı açılamadı vb.). ::: ## Web paywalllarını uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\} :::important Web paywalllarını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15'ten itibaren desteklenmektedir. ::: Varsayılan olarak, web paywallları harici tarayıcıda açılır ve kullanıcıları uygulamanızın dışına yönlendirir. Kesintisiz bir kullanıcı deneyimi sunmak için web paywalllarını bunun yerine uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanız içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir. Bunu etkinleştirmek için `OpenWebPaywall` metoduna `AdaptyWebPresentation.InAppBrowser` değerini geçin: ```csharp showLineNumbers title="Unity" Adapty.OpenWebPaywall( product, AdaptyWebPresentation.InAppBrowser, // default — ExternalBrowser (error) => { if (error != null) { Debug.LogError($"Failed to open web paywall: {error.Message}"); } else { Debug.Log("Web paywall opened successfully"); } } ); ``` --- # File: unity-use-fallback-paywalls --- --- title: "Unity - Yedek paywall kullanımı" description: "Kullanıcılar çevrimdışıyken veya Adapty sunucularına erişilemediğinde bu durumu nasıl yöneteceğinizi öğrenin" --- :::warning Yedek paywall'lar Unity SDK v2.11 ve sonraki sürümlerde desteklenmektedir. ::: Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur. * **Uygulama Adapty sunucularına erişemiyorsa:** Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir. * **Uygulama internete erişemiyorsa:** Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir. :::important Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls). ::: ## Yapılandırma \{#configuration\} 1. Yedek yapılandırma dosyalarını projenizin ortak `Assets/StreamingAssets` dizinine ekleyin. 2. Hedef paywall veya onboarding'i çekmeden **önce** `.setFallback` metodunu çağırın. ```csharp using UnityEngine; using AdaptySDK; #if UNITY_IOS string fileName = "ios_fallback.json"; #elif UNITY_ANDROID string fileName = "android_fallback.json"; #else // Optional: handle Editor or other platforms string fileName = "fallback.json"; #endif Adapty.SetFallback(fileName, (error) => { if (error != null) { Debug.LogError($"Failed to set fallback: {error}"); return; } // Fallback set successfully }); ``` Parametreler: | Parametre | Açıklama | |:-------------|:----------------------------------------------------------------------| | **fileName** | Yedek yapılandırma dosyasının adını içeren string değeri. | --- # File: unity-localizations-and-locale-codes --- --- title: "Unity SDK'da yerelleştirmeleri ve yerel ayar kodlarını kullanma" description: "Adapty SDK ile Unity uygulamanızdaki paywalls'ı nasıl yerelleştireceğinizi öğrenin." --- ## Bu neden önemli \{#why-this-is-important\} Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır; örneğin, uygulamanızın mevcut yerelleştirmesi için doğru paywall'u almaya çalıştığınızda. Yerel ayar kodları karmaşık olup platformdan platforma farklılık gösterebileceğinden, desteklediğimiz tüm platformlar için dahili bir standarda dayanıyoruz. Ancak bu kodlar karmaşık olduğundan, sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; bu sayede her zaman beklediğiniz sonucu alırsınız. ## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\} Adapty, yerel ayar kodları için biraz değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harf alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince). ## Yerel ayar kodu eşleştirme \{#locale-code-matching\} Adapty, istemci tarafı SDK'dan yerel ayar koduyla birlikte bir çağrı aldığında ve paywall'ın ilgili yerelleştirmesini aramaya başladığında şunlar gerçekleşir: 1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgiyle (`-`) değiştirilir 2. Ardından tam olarak eşleşen yerel ayar koduna sahip yerelleştirme aranır 3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır 4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesi döndürülür Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır. ## Yerelleştirmeleri uygulama: önerilen yol \{#implementing-localizations-recommended-way\} Yerelleştirmelerle ilgileniyorsanız, büyük ihtimalle projenizde zaten yerelleştirilmiş string dosyalarıyla çalışıyorsunuzdur. Bu durumda, her dosyanıza ilgili yerelleştirme için amaçlanan Adapty locale kodu ile birlikte bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini şu şekilde çıkarın: ```csharp showLineNumbers // 1. Yerelleştirme dosyalarınızı düzenleyin (örneğin, Unity'nin Localization paketini kullanarak) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Yerel ayar kodunu çıkarın ve kullanın using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; using AdaptySDK; public class PaywallManager : MonoBehaviour { public async void FetchPaywall() { // Unity'nin Localization sisteminden mevcut yerel ayarı alın var locale = LocalizationSettings.SelectedLocale; var localeCode = GetAdaptyLocaleCode(locale); // Yerel ayar kodunu Adapty.GetPaywall veya Adapty.GetPaywallForDefaultAudience metoduna iletin Adapty.GetPaywall("placement_id", localeCode, (paywall, error) => { if (error != null) { // hatayı işle return; } // Paywall'ı kullan }); } private string GetAdaptyLocaleCode(Locale locale) { // Unity yerel ayarını Adapty formatına dönüştür var localeIdentifier = locale.Identifier.Code; return localeIdentifier.ToLower().Replace('_', '-'); } } ``` Bu sayede, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği üzerinde tam kontrole sahip olursunuz. ## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\} Her yerelleştirme için açıkça bir dil kodu tanımlamak zorunda kalmadan benzer (ama aynı değil) sonuçlar elde edebilirsiniz. Bu yaklaşımda, dil kodunu platformunuzun sunduğu başka nesnelerden çıkarabilirsiniz; örneğin: ```csharp showLineNumbers using UnityEngine; using System.Globalization; using AdaptySDK; public class PaywallManager : MonoBehaviour { public void FetchPaywall() { var localeCode = GetSystemLocaleCode(); // Locale kodunu Adapty.GetPaywall veya Adapty.GetPaywallForDefaultAudience metoduna geçirin Adapty.GetPaywall("placement_id", localeCode, (paywall, error) => { if (error != null) { // handle the error return; } // Use the paywall }); } private string GetSystemLocaleCode() { // Sistemin mevcut kültür bilgisini al var culture = CultureInfo.CurrentCulture; var languageCode = culture.TwoLetterISOLanguageName; var regionCode = culture.Name.Contains('-') ? culture.Name.Split('-')[1] : null; if (!string.IsNullOrEmpty(regionCode)) { return $"{languageCode}-{regionCode.ToLower()}"; } return languageCode; } } ``` Bu yaklaşımı birkaç nedenden dolayı önermediğimizi belirtmek gerekir: 1. iOS'ta tercih edilen diller ile mevcut yerel ayar (locale) aynı şey değildir. Yerelleştirmenin doğru seçilmesini istiyorsanız, ya yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda kutudan çıktığı gibi çalışan Apple'ın mantığına güvenmeniz ya da bunu kendiniz yeniden oluşturmanız gerekir. 2. Adapty'nin sunucusunun tam olarak ne alacağını tahmin etmek güçtür. Örneğin iOS'ta, bir cihazda `ar_OM@numbers='latn'` gibi bir yerel ayar elde edip sunucumuza gönderebilirsiniz. Bu durumda aradığınız `ar-om` yerelleştirmesini değil, büyük ihtimalle beklemediğiniz `ar` yerelleştirmesini alırsınız. Bu yaklaşımı kullanmaya karar verirseniz, ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun. --- # File: unity-troubleshoot-paywall-builder --- --- title: "Unity SDK'da Paywall Builder Sorunlarını Giderme" description: "Unity SDK'da Paywall Builder Sorunlarını Giderme" --- Bu kılavuz, Unity SDK'da Adapty Paywall Builder ile tasarlanmış paywall'ları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\} **Sorun**: `CreateView` metodu paywall yapılandırmasını alamıyor. **Neden**: Paywall, Paywall Builder'da cihazda gösterim için etkinleştirilmemiş. **Çözüm**: Paywall Builder'da **Show on device** geçişini etkinleştirin. <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Paywall görüntüleme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\} **Sorun**: Paywall görüntüleme sayısı beklenenin iki katını gösteriyor. **Neden**: Kodunuzda `LogShowPaywall` çağırıyor olabilirsiniz; Paywall Builder kullanıyorsanız bu, görüntüleme sayısını çiftler. Paywall Builder ile tasarlanmış paywall'larda analitikler otomatik olarak izlenir, dolayısıyla bu metodu kullanmanıza gerek yoktur. **Çözüm**: Paywall Builder kullanıyorsanız kodunuzda `LogShowPaywall` çağırmadığınızdan emin olun. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka Paywall Builder ile ilgili sorunlar yaşıyorsunuz. **Çözüm**: Gerekirse [migration kılavuzlarını](unity-sdk-migration-guides) kullanarak SDK'yı en son sürüme geçirin. Birçok sorun yeni SDK sürümlerinde çözülmüştür. --- # File: unity-quickstart-manual --- --- title: "Unity SDK'da özel paywallınızda satın alma işlemlerini etkinleştirme" description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel Unity paywalllarınıza entegre edin." --- Bu kılavuz, Adapty'yi özel paywalllarınıza nasıl entegre edeceğinizi açıklar. Paywall uygulaması üzerinde tam kontrolü elinizde tutarken Adapty SDK ürünleri getirir, yeni satın alma işlemlerini yönetir ve önceki satın almaları geri yükler. :::important **Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu arıyorsanız [Adapty Paywall Builder](unity-quickstart-paywalls)'ı kullanın. Paywall Builder ile paywallları kodsuz görsel düzenleyicide oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz. ::: ## Başlamadan önce \{#before-you-start\} ### Ürünleri ayarlama \{#set-up-products\} Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir: - [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim) - [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de ürünleri almanın tek yolu paywalllar üzerindendir; ancak bu yapı sayesinde uygulama kodunuza dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz. - [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'si ile bunları talep edersiniz. Bu yapı, A/B testleri çalıştırmayı ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır. Özel paywall kullanıyor olsanız bile bu kavramları anladığınızdan emin olun. Bunlar temelde uygulamanızda sattığınız ürünleri yönetme yönteminizdir. Özel paywallınızı uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu kurulum, ürünlerinizi almanızı sağlar. Kontrol panelinde yapmanız gerekenleri anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin. ### Kullanıcıları yönetme \{#manage-users\} Kendi tarafınızda backend kimlik doğrulaması ile veya olmadan çalışabilirsiniz. Ancak Adapty SDK, anonim ve tanımlanmış kullanıcıları farklı şekilde ele alır. Ayrıntıları anlamak ve kullanıcılarla düzgün şekilde çalıştığınızdan emin olmak için [kimlik belirleme hızlı başlangıç kılavuzunu](unity-quickstart-identify) okuyun. ## Adım 1. Ürünleri alın \{#step-1-get-products\} Özel paywallınız için ürünleri almak üzere şunları yapmanız gerekir: 1. [placement](placements) ID'sini `getPaywall` metoduna geçirerek `paywall` nesnesini alın. 2. `getPaywallProducts` metodunu kullanarak bu paywall için ürünler dizisini alın. ```csharp showLineNumbers using AdaptySDK; void LoadPaywall() { Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // Handle the error return; } Adapty.GetPaywallProducts(paywall, (products, productsError) => { if (productsError != null) { // Handle the error return; } // Use products to build your custom paywall UI }); }); } ``` ## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\} Kullanıcı özel paywallınızda bir ürüne dokunduğunda, seçili ürünle `makePurchase` metodunu çağırın. Bu işlem satın alma akışını yönetir ve güncellenmiş profili döndürür. ```csharp showLineNumbers using AdaptySDK; void PurchaseProduct(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { if (error != null) { // Handle the error return; } switch (result.Type) { case AdaptyPurchaseResultType.Success: var profile = result.Profile; // Purchase successful, profile updated break; case AdaptyPurchaseResultType.UserCancelled: // User canceled the purchase break; case AdaptyPurchaseResultType.Pending: // Purchase is pending (e.g., user will pay offline with cash) break; } }); } ``` ## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\} Uygulama mağazaları, abonelik içeren tüm uygulamaların kullanıcılara satın almalarını geri yükleyebilecekleri bir yol sunmasını zorunlu kılar. Kullanıcı geri yükleme düğmesine dokunduğunda `restorePurchases` metodunu çağırın. Bu işlem, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür. ```csharp showLineNumbers using AdaptySDK; void RestorePurchases() { Adapty.RestorePurchases((profile, error) => { if (error != null) { // Handle the error return; } // Restore successful, profile updated }); } ``` ## Sonraki adımlar \{#next-steps\} :::tip Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada! ::: Paywallınız uygulamada gösterilmeye hazır. Paywalldan bir test satın alması tamamlayabildiğinizden emin olmak için satın almalarınızı [App Store sandbox](test-purchases-in-sandbox) ortamında veya [Google Play Store](testing-on-android)'da test edin. Ardından, paywallı gösterip göstermeyeceğinizi ya da ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın alma işlemini tamamlayıp tamamlamadığını kontrol edin](unity-check-subscription-status). --- # File: fetch-paywalls-and-products-unity --- --- title: "Unity SDK'da remote config paywalllar için paywallları ve ürünleri çekme" description: "Kullanıcı gelirini artırmak için Adapty Unity SDK'da paywallları ve ürünleri çekin." --- Remote config ve özel paywallları göstermeden önce, bunlara ilişkin bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywalllar için çekme işlemine dair rehber için [Paywall Builder paywalllarını ve yapılandırmalarını çekme](unity-get-pb-paywalls) bölümüne bakın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: <details> <summary>Mobil uygulamanızda paywallları ve ürünleri çekmeye başlamadan önce (genişletmek için tıklayın)</summary> 1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product). 2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri paywalla ekleyin](create-paywall). 3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywallınızı placement'a ekleyin](create-placement). 4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-unity). </details> ## Paywall bilgilerini çekme \{#fetch-paywall-information\} Adapty'de bir [ürün](product), App Store ve Google Play'deki ürünlerin birleşimidir. Bu platformlar arası ürünler paywallara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar. Ürünleri görüntülemek için `getPaywall` metodunu kullanarak [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir. :::important **Ürün ID'lerini koda sabit olarak yazmayın.** Koda sabit olarak yazmanız gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak işleyebilmelidir — bugün bir paywall iki ürün döndürüyorsa ve yarın üç ürün döndürüyorsa, kod değişikliği gerektirmeden hepsini görüntüleyin. ::: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` | Parametre | Zorunluluk | Açıklama | |---------|--------|-----------| | **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p><p></p><p>Yerel ayar kodları ve bunların nasıl kullanılması önerildiğine dair daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](unity-localizations-and-locale-codes) bölümüne bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](unity-use-fallback-paywalls). Paywallları daha hızlı çekmek için CDN kullanıyoruz ve CDN'e erişilemediği durumlarda bağımsız bir yedek sunucu devreye giriyor. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veriler veya yerel yedek döndürülür.</p><p></p><p>Nadir durumlarda bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın, çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Ürün ID'lerini koda sabit olarak yazmayın! Paywalllar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz denemeler gibi) zamanla değişebilir. Kodunuzun bu senaryoları işlediğinden emin olun. Örneğin, başlangıçta 2 ürün alırsanız uygulamanız o 2 ürünü görüntülemelidir. Ancak daha sonra 3 ürün alırsanız, uygulamanız herhangi bir kod değişikliği gerektirmeden 3 ürünün tamamını görüntülemelidir. Koda sabit olarak yazmanız gereken tek şey placement ID'sidir. Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Ürün ID'leri listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özelliklerle birlikte bir [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesi. | ## Ürünleri çekme \{#fetch-products\} Paywallı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz: ```csharp showLineNumbers Adapty.GetPaywallProducts(paywall, (products, error) => { if(error != null) { // handle the error return; } // products - the requested products array }); ``` Yanıt parametreleri: | Parametre | Açıklama | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özelliklerle birlikte [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) nesnelerinin listesi. | Kendi paywall tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) nesnesindeki bu özelliklere erişmeniz gerekecektir. Aşağıda en sık kullanılan özellikler gösterilmektedir; ancak mevcut tüm özelliklere ilişkin tam ayrıntılar için bağlantılı belgeye başvurun. | Özellik | Açıklama | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Ürünün başlığını görüntülemek için `product.LocalizedTitle` kullanın. Yerelleştirmenin cihazın yerel ayarına değil, kullanıcıların seçtiği mağaza ülkesine göre yapıldığını unutmayın. | | **Price** | Fiyatın yerelleştirilmiş sürümünü görüntülemek için `product.Price.LocalizedString` kullanın. Bu yerelleştirme, cihazın yerel ayar bilgisine dayanır. Fiyata sayı olarak `product.Price.Amount` üzerinden de erişebilirsiniz. Değer yerel para birimi cinsinden sağlanacaktır. İlişkili para birimi sembolünü almak için `product.Price.CurrencySymbol` kullanın. | | **Subscription Period** | Dönemi (ör. hafta, ay, yıl vb.) görüntülemek için `product.Subscription?.LocalizedPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına dayanır. Abonelik dönemini programatik olarak almak için `product.Subscription?.Period` kullanın. Oradan uzunluğu almak için `Unit` enum'una erişebilirsiniz (`AdaptySubscriptionPeriodUnit.Day`, `AdaptySubscriptionPeriodUnit.Week`, `AdaptySubscriptionPeriodUnit.Month`, `AdaptySubscriptionPeriodUnit.Year` veya `AdaptySubscriptionPeriodUnit.Unknown`). `NumberOfUnits` değeri, dönem birimi sayısını verir. Örneğin, üç aylık bir abonelik için Unit özelliğinde `AdaptySubscriptionPeriodUnit.Month`, NumberOfUnits özelliğinde `3` görürsünüz. | | **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerdiğini belirten bir rozet veya gösterge görüntülemek için `product.Subscription?.Offer?.Phases` özelliğine bakın. Bu, ücretsiz deneme aşaması ve başlangıç fiyatı aşaması olmak üzere iki indirim aşamasına kadar içerebilen bir listedir. Her aşama nesnesi içinde şu yararlı özellikler bulunur:<br/>• `PaymentMode`: `AdaptyPaymentMode.FreeTrial`, `AdaptyPaymentMode.PayAsYouGo`, `AdaptyPaymentMode.PayUpFront` ve `AdaptyPaymentMode.Unknown` değerlerine sahip bir enum. Ücretsiz denemeler `AdaptyPaymentMode.FreeTrial` türünde olacaktır.<br/>• `Price`: İndirimli fiyat sayı olarak. Ücretsiz denemeler için burada `0` arayın.<br/>• `LocalizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarıyla yerelleştirilmiş olarak açıklayan bir dize. Örneğin, üç günlük bir deneme teklifi bu alanda `"3 days"` gösterir.<br/>• `SubscriptionPeriod`: Alternatif olarak, teklif döneminin bireysel ayrıntılarını bu özellikle alabilirsiniz. Teklifler için önceki bölümün açıkladığıyla aynı şekilde çalışır.<br/>• `LocalizedSubscriptionPeriod`: Kullanıcının yerel ayarı için biçimlendirilmiş indirim abonelik dönemi. | ## Varsayılan kitle paywallıyla paywall çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\} Genellikle paywalllar neredeyse anında çekilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitleniz ve paywallınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir paywallı çekmek istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz. Bunu ele almak için, belirtilen placement'ın **Tüm Kullanıcılar** kitlesi için paywallı çeken `GetPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](#fetch-paywall) bölümünde açıklandığı gibi `getPaywall` metodunu kullanmak olduğunu anlamak önemlidir. :::warning `GetPaywallForDefaultAudience` yerine `GetPaywall` kullanmayı düşünün; çünkü ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlar yaratabilir; geriye dönük uyumlu tasarımlar gerektirmek veya eski sürümlerin yanlış görüntülenebileceğini kabul etmek zorunlu kalabilirsiniz. - **Kişiselleştirme yok**: Yalnızca "Tüm Kullanıcılar" kitlesi için içerik gösterir; ülke, attribution veya özel özniteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuz için daha hızlı çekme bu dezavantajlardan ağır basıyorsa, aşağıda gösterildiği gibi `GetPaywallForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-paywall) açıklandığı gibi `GetPaywall` kullanın. ::: ```csharp showLineNumbers Adapty.GetPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Paywall yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış verileri döndürür. Kullanıcılarınızın her zaman en güncel verileri almasını sağladığından bu seçeneği öneriyoruz.</p><p></p><p>Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel verileri alamayabilir, ancak internet bağlantıları ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerinden kaçınmak için oturum boyunca kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yoluyla silindiğini unutmayın.</p><p></p><p>Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek paywalllar. Paywallları daha hızlı çekmek için CDN kullanıyoruz ve CDN'e erişilemediği durumlarda bağımsız bir yedek sunucu devreye giriyor. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.</p> | --- # File: present-remote-config-paywalls-unity --- --- title: "Unity SDK'da remote config ile tasarlanan paywallı render etme" description: "Adapty Unity SDK'da remote config paywalllarının nasıl sunulacağını ve kullanıcı deneyiminin nasıl kişiselleştirileceğini keşfedin." --- Bir paywallı remote config kullanarak özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulama kodunuzda render işlemini kendiniz yapmanız gerekir. Remote config, ihtiyaçlarınıza göre esneklik sunduğundan, paywallınıza nelerin dahil olacağını ve görünümünün nasıl olacağını siz belirlersiniz. Remote config aracılığıyla yapılandırılmış özel paywallınızı gösterebilmek için remote yapılandırmayı çekmeye yarayan bir yöntem sunuyoruz. ## Paywall remote config'ini alın ve sunun \{#get-paywall-remote-config-and-present-it\} Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve ihtiyaç duyduğunuz değerleri çekin. ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } // Access remote config dictionary var dictionary = paywall.RemoteConfig?.Dictionary; var headerText = dictionary?["header_text"] as string; // Or access raw JSON data var jsonData = paywall.RemoteConfig?.Data; }); ``` Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfaya dönüştürme zamanı gelmiştir. Tasarımın farklı telefon ekranlarına ve yönlendirmelerine uyum sağladığından, tüm cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunduğundan emin olun. :::warning Adapty analitiğinin huni ve A/B testi verilerini doğru kaydedebilmesi için aşağıda açıklandığı şekilde [paywall görüntüleme etkinliğini kaydettiğinizden](present-remote-config-paywalls-unity#track-paywall-view-events) emin olun. ::: Paywallı göstermeyi tamamladıktan sonra satın alma akışını kurabilirsiniz. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.MakePurchase()` yöntemini çağırmanız yeterlidir. `.MakePurchase()` yöntemi hakkında ayrıntılı bilgi için [Satın alma yapma](unity-making-purchases) bölümüne bakın. [Yedek paywall olarak adlandırılan bir fallback paywall oluşturmanızı](unity-use-fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar. ## Paywall görüntüleme etkinliklerini takip edin \{#track-paywall-view-events\} Adapty, paywalllarınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da paywall görüntülemelerini kaydetmek sizin sorumluluğunuzdadır; çünkü bir müşterinin paywallı ne zaman gördüğünü yalnızca siz bilebilirsiniz. Bir paywall görüntüleme etkinliği kaydetmek için `.LogShowPaywall(paywall)` yöntemini çağırmanız yeterlidir; bu işlem, huni ve A/B testi metriklerinize yansıyacaktır. :::important [Paywall Builder](adapty-paywall-builder) ile oluşturulan paywallları gösteriyorsanız `.LogShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur. ::: ```csharp showLineNumbers Adapty.LogShowPaywall(paywall, (error) => { // handle the error }); ``` İstek parametreleri: | Parametre | Zorunluluk | Açıklama | | :---------- | :--------- |:---------------------------------------------------------------| | **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesi. | --- # File: unity-making-purchases --- --- title: "Unity SDK ile mobil uygulamada satın alma yapma" description: "Adapty kullanarak uygulama içi satın almaları ve abonelikleri yönetme kılavuzu." --- Mobil uygulamanızda paywall'ları göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak, paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, bu paywall'ları yalnızca göstermek satın almaları desteklemek için yeterlidir. Paywall Builder kullanmıyorsanız, satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime geçmesini ve istedikleri işlemleri gerçekleştirmesini sağlayan kapı işlevi görür. Eğer paywallınızda kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa, Adapty bunu satın alma sırasında otomatik olarak uygular. :::warning Başlangıç teklifinin otomatik olarak uygulanabilmesi için Paywall Builder ile oluşturulmuş paywallları kullanmanız gerektiğini unutmayın. Diğer durumlarda, [iOS'ta kullanıcının başlangıç teklifi için uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekecektir. Bu adımı atlamak, uygulamanızın yayın sürecinde reddedilmesine yol açabilir. Bunun yanı sıra, başlangıç teklifine uygun olan kullanıcılardan tam fiyat alınmasına neden olabilir. ::: [Başlangıç yapılandırmasını](quickstart) tek bir adımı bile atlamadan tamamladığınızdan emin olun. Bu olmadan satın alımları doğrulayamayız. ## Satın alma yapma \{#make-purchase\} :::note **[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir—bu adımı atlayabilirsiniz. **Adım adım rehber mi arıyorsunuz?** Tam bağlam içeren uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](unity-implement-paywalls-manually) göz atın. ::: ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successfull purchase break; default: break; } }); } ``` İstek parametreleri: | Parametre | Varlık | Açıklama | | :---------- | :------- |:---------------------------------------------------------------------------------------------------| | **Product** | gerekli | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) nesnesi. | Yanıt parametreleri: | Parametre | Açıklama | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>İstek başarılı olursa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) nesnesi, kullanıcının uygulama içindeki access level'ları, abonelikleri ve tek seferlik satın almaları hakkında kapsamlı bilgi sağlar.</p><p>Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.</p> | :::warning **Not:** Hâlâ Apple'ın StoreKit v2.0'dan düşük bir sürümünü ve Adapty SDK'nın v2.9.0'dan düşük bir sürümünü kullanıyorsanız, bunun yerine [Apple App Store paylaşılan secret'ı](app-store-connection-configuration#step-5-enter-app-store-shared-secret) sağlamanız gerekir. Bu yöntem Apple tarafından kullanımdan kaldırılmıştır. ::: ## Satın alma sırasında aboneliği değiştirme \{#change-subscription-when-making-a-purchase\} Bir kullanıcı mevcut aboneliğini yenilemek yerine yeni bir abonelik seçtiğinde, bu süreç uygulama mağazasına göre farklı işler: - App Store'da abonelik, abonelik grubu içinde otomatik olarak güncellenir. Kullanıcı bir gruptan abonelik satın alırken başka bir gruptan zaten aktif bir aboneliği varsa, her iki abonelik aynı anda aktif olur. - Google Play'de abonelik otomatik olarak güncellenmez. Geçişi, aşağıda açıklandığı gibi mobil uygulama kodunuzda yönetmeniz gerekir. Android'de aboneliği başka biriyle değiştirmek için `.makePurchase()` metodunu ek parametre ile çağırın: ```csharp showLineNumbers // Create subscription update parameters var subscriptionUpdateParams = new AdaptySubscriptionUpdateParameters( "old_product_id", // Product ID of the current subscription AdaptySubscriptionUpdateReplacementMode.WithTimeProration ); Adapty.MakePurchase(product, subscriptionUpdateParams, (profile, error) => { if(error != null) { // Handle the error return; } // successful cross-grade }); ``` Ek istek parametresi: | Parametre | Varlık | Açıklama | | :--------------------------- | :------- |:-------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | zorunlu | bir [`AdaptySubscriptionUpdateParameters`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_subscription_update_parameters.html) nesnesi. | Abonelikler ve değiştirme modları hakkında daha fazla bilgi edinmek için Google Geliştirici belgelerine bakabilirsiniz: - [Değiştirme modları hakkında](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google'ın değiştirme modları için önerileri](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Değiştirme modu [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Not: Bu yöntem yalnızca abonelik yükseltmeleri için kullanılabilir. Düşürme işlemleri desteklenmez. - Değiştirme modu [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Not: Gerçek abonelik değişikliği yalnızca mevcut abonelik fatura dönemi sona erdiğinde gerçekleşir. ## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\} <Details> <summary>Teklif kodları hakkında</summary> Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir. Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz: - **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir. - **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir. - **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir. Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz. #### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\} Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın: - Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır. - Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir. Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz. #### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\} :::warning Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın. ::: Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu. Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın. </Details> Uygulamanızda kod kullanma sayfasını göstermek için: ```csharp showLineNumbers Adapty.PresentCodeRedemptionSheet((error) => { // handle the error }); ``` :::danger Gözlemlerimize göre, bazı uygulamalarda Teklif Kodu Kullanma sayfası güvenilir biçimde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz. Bunu yapmak için aşağıdaki formattaki URL'yi açmanız gerekir: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## Ön ödemeli planları yönetme (Android) \{#manage-prepaid-plans-android\} Uygulama kullanıcılarınız [ön ödemeli planlar](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) satın alabiliyorsa (örneğin, birkaç aylık yenilenmeyen bir abonelik), ön ödemeli planlar için [bekleyen işlemleri](https://developer.android.com/google/play/billing/subscriptions#pending) etkinleştirebilirsiniz. ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetGoogleEnablePendingPrepaidPlans(true); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` --- # File: unity-restore-purchase --- --- title: "Unity SDK'da mobil uygulamada satın alımları geri yükleme" description: "Sorunsuz bir kullanıcı deneyimi sağlamak için Adapty'de satın alımları nasıl geri yükleyeceğinizi öğrenin." --- Hem iOS hem de Android'de satın alımları geri yükleme; kullanıcıların abonelikler veya uygulama içi satın alımlar gibi daha önce satın aldıkları içeriklere tekrar ücret ödemeden yeniden erişmesini sağlayan bir özelliktir. Bu özellik, uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve önceki satın alımlarına tekrar erişmek isteyen kullanıcılar için oldukça kullanışlıdır. :::note [Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywallarda satın alımlar, sizin tarafınızdan ek bir kod gerekmeksizin otomatik olarak geri yüklenir. Bu durum sizin için geçerliyse bu adımı atlayabilirsiniz. ::: Paywallı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın alımı geri yüklemek için `.restorePurchases()` metodunu çağırın: ```csharp showLineNumbers Adapty.RestorePurchases((profile, error) => { if (error != null) { // handle the error return; } var accessLevel = profile.AccessLevels["YOUR_ACCESS_LEVEL"]; if (accessLevel != null && accessLevel.IsActive) { // restore access } }); ``` Yanıt parametreleri: | Parametre | Açıklama | |---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>Bir [`AdaptyProfile`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) nesnesi. Bu model; access level, abonelik ve abonelik dışı satın alımlara ilişkin bilgileri içerir.</p><p>Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.</p> | :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: --- # File: implement-observer-mode-unity --- --- title: "Unity SDK'da Observer modu uygulama" description: "Unity SDK'da kullanıcı abonelik olaylarını izlemek için Adapty'de observer modunu uygulayın." --- Kendi satın alma altyapınız varsa ve Adapty'ye tamamen geçmeye hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer modu; gelişmiş analitik ve attribution ile analitik sistemlerle sorunsuz entegrasyon sunar. Bu ihtiyaçlarınızı karşılıyorsa yalnızca şunları yapmanız yeterli: 1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak Observer modunu etkinleştirin. Kurulum talimatlarını [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk) için takip edin. 2. Mevcut satın alma altyapınızdaki işlemleri [Adapty'ye bildirin](report-transactions-observer-mode-unity). ### Observer modu kurulumu \{#observer-mode-setup\} Satın alma ve abonelik durumunu kendiniz yönetiyorsanız ve Adapty'yi yalnızca abonelik olayları ile analitik göndermek için kullanıyorsanız Observer modunu etkinleştirin. :::important Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle bunu kendiniz yönettiğinizden emin olun. ::: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetObserverMode(true); // Enable observer mode Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` Parametreler: | Parametre | Açıklama | |--------------|------------------------------------------------------------------------------------------------------------| | observerMode | [Observer modu](observer-vs-full-mode)'nu kontrol eden boolean değer. Varsayılan değer `false`'tur. | ## Observer Modunda Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\} Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz; ancak Observer modunda birkaç ek adım gerekir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir: 1. [Remote config paywall'ları](present-remote-config-paywalls-unity) için paywall'ları her zamanki gibi gösterin. 3. Satın alma işlemleriyle [paywall'ları ilişkilendirin](report-transactions-observer-mode-unity). --- # File: report-transactions-observer-mode-unity --- --- title: "Unity SDK'da Observer Mode'da işlemleri raporlama" description: "Unity SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini raporlayın." --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+ (güncel)" default> Observer modunda Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. Uygulama mağazanızdaki işlemleri manuel olarak raporlamanız gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız kritik önem taşır. Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanarak açıkça raporlayın. :::warning **İşlem raporlamayı atlamayın!** `ReportTransaction` çağrısı yapmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'ları kullanıyorsanız, bir işlemi raporlarken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve doğru paywall analitikleri sağlar. ```csharp showLineNumbers Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | zorunlu | <ul><li> iOS için: İşlemin tanımlayıcısı.</li><li> Android için: Satın almanın String tanımlayıcısı `purchase.getOrderId`; burada satın alma, billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | variationId | isteğe bağlı | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x (eski)" default> Observer modunda Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. Uygulama mağazanızdaki işlemleri raporlamanız ya da geri yüklemeniz gerekir. Analizlerdeki hataları önlemek için bunu uygulamanızı yayınlamadan **önce** yapılandırmanız kritik önem taşır. Her işlemi açıkça raporlamak için her iki platformda da `reportTransaction` kullanın; Android'de Adapty'nin işlemi tanıdığından emin olmak için ek adım olarak `restorePurchases` çağrısı yapın. :::warning **İşlem raporlamayı ve satın alma geri yüklemeyi atlamayın!** Bu metodları çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: Adapty paywall'ları kullanıyorsanız, bir işlemi raporlarken `PAYWALL_VARIATION_ID` değerini de ekleyin. Bu, satın almayı tetikleyen paywall ile ilişkilendirir ve doğru paywall analitikleri sağlar. ```csharp showLineNumbers // every time when calling transasction.finish() #if UNITY_ANDROID && !UNITY_EDITOR Adapty.RestorePurchases((profile, error) => { // handle the error }); #endif Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | | ------------- | -------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | zorunlu | <ul><li> iOS, StoreKit 1 için: [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</li><li> iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</li><li> Android için: Satın almanın String tanımlayıcısı (`purchase.getOrderId`); burada satın alma, billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</li></ul> | | variationId | isteğe bağlı | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> <TabItem value="old2" label="Adapty SDK 3.2.x ve altı (eski)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **İşlemleri raporlama** - 3.1.x ve önceki sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel raporlama gerekmez. - 3.2 sürümü Observer Mode'u desteklememektedir. </TabItem> <TabItem value="kotlin" label="Android and Android-based cross-platforms" default> **İşlemleri raporlama** Observer Mode'da Adapty'ye bir işlem raporlamak için `restorePurchases` kullanın. Ayrıntılar için [Mobil Kodda Satın Almaları Geri Yükleme](unity-restore-purchase) sayfasına bakın. :::warning **İşlem raporlamayı atlamayın!** `restorePurchases` çağrısı yapmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: </TabItem> </Tabs> **Paywall'ları işlemlerle ilişkilendirme** Adapty SDK, satın almaların kaynağını belirleyemez; zira bu işlemleri siz gerçekleştirirsiniz. Bu nedenle Observer modunda paywall ve/veya A/B testi kullanmayı planlıyorsanız, uygulama mağazanızdan gelen işlemi mobil uygulama kodunuzda ilgili paywall ile ilişkilendirmeniz gerekir. Bunu uygulamanızı yayınlamadan önce doğru şekilde yapılandırmanız önemlidir; aksi takdirde analizlerde hatalara yol açar. ```csharp Adapty.SetVariationForTransaction("<variationId>", "<transactionId>", (error) => { if(error != null) { // handle the error return; } // successful binding }); ``` | Parametre | Zorunluluk | Açıklama | | ------------------------------------------------------ | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | zorunlu | <p>iOS, StoreKit 1 için: [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) nesnesi.</p><p>iOS, StoreKit 2 için: [Transaction](https://developer.apple.com/documentation/storekit/transaction) nesnesi.</p><p>Android için: Satın almanın String tanımlayıcısı (purchase.getOrderId); burada satın alma, billing library [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) sınıfının bir örneğidir.</p> | | variationId | zorunlu | Varyasyonun string tanımlayıcısı. [AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) nesnesinin `variationId` özelliği kullanılarak elde edilebilir. | </TabItem> </Tabs> --- # File: unity-troubleshoot-purchases --- --- title: "Unity SDK'da satın alma sorunlarını giderme" description: "Unity SDK'da satın alma sorunlarını giderme" --- Bu kılavuz, Unity SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur. ## makePurchase başarıyla çağrılıyor, ancak profil güncellenmiyor \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Sorun**: `makePurchase` metodu başarıyla tamamlanıyor, ancak kullanıcının profili ve abonelik durumu Adapty'de güncellenmiyor. **Neden**: Bu genellikle Google Play Store kurulumunun eksik ya da yanlış yapılandırıldığını gösterir. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## makePurchase iki kez tetikleniyor \{#makepurchase-is-invoked-twice\} **Sorun**: Aynı satın alma için `makePurchase` metodu birden fazla kez çağrılıyor. **Neden**: Bu durum genellikle UI durum yönetimi sorunları veya kullanıcının hızlı ardışık etkileşimleri nedeniyle satın alma akışının birden fazla kez tetiklenmesinden kaynaklanır. **Çözüm**: Tüm [Google Play kurulum adımlarını](initial-android) tamamladığınızdan emin olun. ## Observer modda AdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **Sorun**: Observer modda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz. **Neden**: Observer modda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız. **Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanın ya da observer modunda satın almaları kendi tarafınızda yönetin. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode-unity) sayfasına bakın. ## Adapty hatası: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Sorun**: Google Play Store'dan faturalandırmanın kullanılamadığına dair bir hata alıyorsunuz. **Neden**: Bu hata Adapty ile ilgili değildir. Cihazda faturalandırmanın mevcut olmadığını belirten bir Google Play Billing Library hatasıdır. **Çözüm**: Bu hata Adapty ile ilgili değildir. Daha fazla bilgi için Play Store belgelerine göz atabilirsiniz: [BillingResult yanıt kodlarını yönetme](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## makePurchasesCompletionHandlers bulunamadı \{#not-found-makepurchasescompletionhandlers\} **Sorun**: `makePurchasesCompletionHandlers` bulunamadığına dair sorunlarla karşılaşıyorsunuz. **Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir. **Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu yöntem, sandbox ile ilgili satın alma tamamlama işleyicisi sorunlarını çoğunlukla çözer. ## Diğer sorunlar \{#other-issues\} **Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz. **Çözüm**: Gerekirse SDK'yı [geçiş kılavuzlarını](unity-sdk-migration-guides) kullanarak en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde giderilmiştir. --- # File: unity-identifying-users --- --- title: "Unity SDK'da kullanıcıları tanımlama" description: "Adapty SDK ile Unity uygulamanızdaki kullanıcıları nasıl tanımlayacağınızı öğrenin." --- Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi belirlemeniz gerekir. Kullanıcıları Customer User ID'leriyle [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [sunucu taraflı API](getting-started-with-server-side-api)'de kullanabilirsiniz. ### Yapılandırma sırasında customer user ID belirleme \{#setting-customer-user-id-on-configuration\} Yapılandırma sırasında bir kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçin: ```csharp showLineNumbers using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### Yapılandırma sonrasında customer user ID belirleme \{#setting-customer-user-id-after-configuration\} SDK yapılandırması sırasında kullanıcı ID'niz yoksa, `.identify()` metodunu kullanarak bunu istediğiniz zaman sonradan ayarlayabilirsiniz. Bu metodun en yaygın kullanım senaryoları; kayıt veya oturum açma sonrasında kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçiş yaptığı durumlardır. ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { if(error == null) { // successful identify } }); ``` İstek parametreleri: - **Customer User ID** (zorunlu): Bir string kullanıcı tanımlayıcısı. :::warning Önemli kullanıcı verilerinin yeniden gönderilmesi Kullanıcının hesabına yeniden giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları söz konusu kullanıcı hakkında zaten bilgiye sahiptir. Bu senaryolarda Adapty SDK, yeni kullanıcıyla çalışmaya otomatik olarak geçiş yapar. Anonim kullanıcıya özel nitelikler veya üçüncü taraf ağlardan attribution verileri gibi herhangi bir veri aktardıysanız, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir. Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden talep etmeniz gerektiğini unutmayın. ::: ### Oturum kapatma ve açma \{#logging-out-and-logging-in\} `.logout()` metodunu çağırarak kullanıcının oturumunu istediğiniz zaman kapatabilirsiniz: ```csharp showLineNumbers Adapty.Logout((error) => { if(error == null) { // successful logout } }); ``` Ardından `.identify()` metodunu kullanarak kullanıcının oturumunu açabilirsiniz. ## `appAccountToken` atama (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinizle ilişkilendirmenizi sağlayan bir **UUID**'dir. StoreKit bu token'ı her işlemle ilişkilendirir; böylece arka ucunuz App Store verilerini kullanıcılarınızla eşleştirebilir. Kullanıcı başına oluşturulan kararlı bir UUID kullanın ve aynı hesap için farklı cihazlarda bu UUID'yi yeniden kullanın. Bu sayede satın almalar ve App Store bildirimleri doğru şekilde ilişkilendirilmiş kalır. Token'ı iki şekilde ayarlayabilirsiniz: SDK aktivasyonu sırasında veya kullanıcıyı tanımlarken. :::important `appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmelisiniz. Yalnızca token'ı geçerseniz, bu işleme dahil edilmez. ::: ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; using System; // During configuration: var appAccountToken = new Guid("YOUR_APP_ACCOUNT_TOKEN"); var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID", appAccountToken); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); // Or when identifying users Adapty.Identify("YOUR_USER_ID", appAccountToken, (error) => { if (error == null) { // successful identify } }); ``` ## Gizlenmiş hesap ID'lerini ayarlama (Android) \{#set-obfuscated-account-ids-android\} Google Play, kullanıcı gizliliğini ve güvenliğini artırmak amacıyla belirli kullanım senaryoları için gizlenmiş hesap ID'leri gerektirir. Bu ID'ler, Google Play'in kullanıcı bilgilerini anonim tutarken satın almaları tanımlamasına yardımcı olur; bu özellikle dolandırıcılığın önlenmesi ve analitik açısından önemlidir. Uygulamanız hassas kullanıcı verileri işliyorsa veya belirli gizlilik düzenlemelerine uymak zorundaysanız bu ID'leri ayarlamanız gerekebilir. Gizlenmiş ID'ler, Google Play'in gerçek kullanıcı tanımlayıcılarını açığa çıkarmadan satın almaları takip etmesine olanak tanır. ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; // During configuration: var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID", null, "YOUR_OBFUSCATED_ACCOUNT_ID"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); // Or when identifying users Adapty.Identify("YOUR_USER_ID", null, "YOUR_OBFUSCATED_ACCOUNT_ID", (error) => { if (error == null) { // successful identify } }); ``` ## Cihazlar arası kullanıcıları tespit edin \{#detect-users-across-devices\} SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür. Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır. **Adapty'nin cihazlar arasında neleri algılayabildiği** | Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken | | --- | --- | --- | | Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. | | Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. | | Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. | | Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. | **Yeni bir cihazda satın almaları geri yükleme** Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır. İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken. --- # File: unity-setting-user-attributes --- --- title: "Unity SDK'da kullanıcı nitelikleri ayarlama" description: "Adapty SDK ile Unity uygulamanızda kullanıcı niteliklerini ve profil verilerini nasıl güncelleyeceğinizi öğrenin." --- Uygulamanızın kullanıcısına e-posta, telefon numarası gibi isteğe bağlı nitelikler ekleyebilirsiniz. Bu nitelikleri kullanarak kullanıcı [segmentleri](segments) oluşturabilir ya da bunları CRM'de görüntüleyebilirsiniz. ### Kullanıcı niteliklerini ayarlama \{#setting-user-attributes\} Kullanıcı niteliklerini ayarlamak için `.updateProfile()` metodunu çağırın: ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetFirstName("John") .SetLastName("Appleseed") .SetBirthday(new DateTime(1970, 1, 3)) .SetGender(ProfileGender.Female) .SetEmail("example@adapty.io"); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != nil) { // handle the error } }); ``` `updateProfile` metoduyla daha önce ayarladığınız niteliklerin sıfırlanmayacağını unutmayın. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ### İzin verilen anahtarlar listesi \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` için izin verilen `<Key>` anahtarları ve `<Value>` değerleri aşağıda listelenmiştir: | Anahtar | Değer | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum, izin verilen değerler: `female`, `male`, `other` | | birthday | Date | ### Özel kullanıcı nitelikleri \{#custom-user-attributes\} Kendi özel niteliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanım şekliyle ilgilidir. Örneğin fitness uygulamaları için haftalık egzersiz sayısı, dil öğrenme uygulamaları için kullanıcının bilgi seviyesi gibi. Bu nitelikleri segmentlerde kullanarak hedefli paywall'lar ve teklifler oluşturabilir; hangi ürün metriklerinin geliri en çok etkilediğini anlamak için de analizlerde kullanabilirsiniz. ```csharp showLineNumbers try { builder = builder.SetCustomStringAttribute("string_key", "string_value"); builder = builder.SetCustomDoubleAttribute("double_key", 123.0f); } catch (Exception e) { // handle the exception } ``` Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın: ```csharp showLineNumbers try { builder = builder.RemoveCustomAttribute("key_to_remove"); } catch (Exception e) { // handle the exception } ``` Bazen daha önce hangi özel niteliklerin yüklendiğini öğrenmek gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın. :::warning `customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı nitelikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, son senkronizasyondan bu yana sunucudaki nitelikler değişmiş olabilir. ::: ### Sınırlar \{#limits\} - Kullanıcı başına en fazla 30 özel nitelik - Anahtar adları en fazla 30 karakter uzunluğunda olabilir. Anahtar adı alfanümerik karakterler ve şunlardan herhangi birini içerebilir: `_` `-` `.` - Değer, en fazla 50 karakterden oluşan bir string veya float olabilir. --- # File: unity-listen-subscription-changes --- --- title: "Unity SDK'da abonelik durumunu kontrol etme" description: "Unity uygulamanızda müşteri tutundurmasını artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin." --- Adapty ile abonelik durumunu takip etmek çok kolay. Ürün ID'lerini kodunuza manuel olarak eklemenize gerek yok. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz. <details> <summary>Abonelik durumunu kontrol etmeye başlamadan önce (Genişletmek için tıklayın)</summary> - iOS için [App Store Server Notifications](enable-app-store-server-notifications) kurulumunu yapın - Android için [Real-time Developer Notifications (RTDN)](enable-real-time-developer-notifications-rtdn) kurulumunu yapın </details> ## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\} Access level'lar, [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) nesnesinin özellikleridir. Profili, uygulamanız başladığında (örneğin [bir kullanıcıyı tanımladığınızda](unity-identifying-users#setting-customer-user-id-on-configuration)) alıp ardından değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini tekrar tekrar istek göndermeden kullanabilirsiniz. Profil güncellemelerinden haberdar olmak için aşağıdaki [Abonelik durumu güncellemelerini dinleme](#listening-for-subscription-status-updates) bölümünde anlatıldığı şekilde profil değişikliklerini dinleyin. :::tip Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın. ::: ## Access level'ı sunucudan alma \{#retrieving-the-access-level-from-the-server\} Access level'ı sunucudan almak için `.GetProfile()` metodunu kullanın: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access }); ``` Yanıt parametreleri: | Parametre | Açıklama | | --------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile | <p>Bir [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) nesnesi. Genellikle, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.</p><p></p><p>`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (örneğin internet bağlantısı yokluğu) Adapty SDK sunucudan bilgi alamazsa önbellekteki veriler döndürülür. Ayrıca Adapty SDK'nın bu bilgileri mümkün olduğunca güncel tutmak için `AdaptyProfile` önbelleğini düzenli aralıklarla güncellediğini de belirtmek gerekir.</p> | `.getProfile()` metodu, access level durumunu alabileceğiniz kullanıcı profilini sağlar. Uygulama başına birden fazla access level tanımlayabilirsiniz. Örneğin bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız, "sports" ve "science" adında access level'lar oluşturabilirsiniz. Ancak çoğu zaman yalnızca bir access level'a ihtiyaç duyulur; bu durumda varsayılan "premium" access level'ı kullanabilirsiniz. Varsayılan "premium" access level'ını kontrol etmek için bir örnek: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // "premium" is an identifier of default access level var accessLevel = profile.AccessLevels["premium"]; if (accessLevel != null && accessLevel.IsActive) { // grant access to premium features } }); ``` ### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\} Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler. Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir: ```csharp showLineNumbers // Extend `AdaptyEventListener ` with `OnLoadLatestProfile ` method: public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle any changes to subscription state } } ``` Adapty, uygulama başlangıcında da bir olay tetikler. Bu durumda önbellekteki abonelik durumu iletilir. ### Abonelik durumu önbelleği \{#subscription-status-cache\} Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucu kullanılamaz olsa bile profil abonelik durumu hakkında bilgi sağlamak için önbellekteki verilere erişilebilir. Ancak önbellekten doğrudan veri isteği yapılamadığını belirtmek gerekir. SDK, profille ilgili güncelleme veya değişiklikleri kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler ya da diğer güncellemeler gibi değişiklikler varsa, sunucuyla senkronizasyonu korumak amacıyla önbellekteki verilere yansıtılır. --- # File: unity-deal-with-att --- --- title: "Unity SDK'da ATT ile Başa Çıkma" description: "Abonelik kurulumu ve yönetimini kolaylaştırmak için Unity'de Adapty'ye başlayın." --- Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama izleme yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir. ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetAppTrackingTransparencyStatus(IOSAppTrackingTransparencyStatus.Authorized); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != null) { // handle the error } }); ``` :::warning Bu değeri, değiştiği anda mümkün olan en erken sürede göndermenizi şiddetle tavsiye ederiz; yalnızca bu durumda veriler, yapılandırdığınız entegrasyonlara zamanında iletilecektir. ::: --- # File: kids-mode-unity --- --- title: "Unity SDK'da Çocuk Modu" description: "Apple ve Google politikalarına uymak için Çocuk Modunu kolayca etkinleştirin. Unity SDK'da IDFA, GAID veya reklam verisi toplanmaz." --- Unity uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) ve [Google](https://support.google.com/googleplay/android-developer/answer/9893335) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikalara uygun şekilde yapılandırabilir ve uygulama mağazası incelemelerini geçebilirsiniz. ## Ne yapmanız gerekiyor? \{#whats-required\} Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir: - [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Bunların yanı sıra, kullanıcı ID'sini dikkatli kullanmanızı öneririz. `<Ad.Soyad>` formatındaki kullanıcı ID'si, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilecektir. Çocuk Modu için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele veya anonimleştirilmiş tanımlayıcılar (ör. karma ID'ler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır. ## Çocuk Modunu Etkinleştirme \{#enabling-kids-mode\} ### Adapty Kontrol Paneli'nde yapılacak güncellemeler \{#updates-in-the-adapty-dashboard\} Adapty Kontrol Paneli'nde IP adresi toplamanın devre dışı bırakılması gerekir. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın. ### Mobil uygulama kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\} Unity'de Çocuk Modu desteği yakında geliyor! Şimdilik aşağıdaki platform kılavuzlarını takip edebilirsiniz: - iOS yapılandırması için [iOS SDK'da Çocuk Modu](kids-mode) - Android yapılandırması için [Android SDK'da Çocuk Modu](kids-mode-android) --- # File: unity-get-onboardings --- --- title: "Unity SDK'da onboarding alma" description: "Unity için Adapty'de onboarding'leri nasıl alacağınızı öğrenin." --- [Adapty Kontrol Paneli'ndeki builder ile onboarding'inizin görsel kısmını tasarladıktan](design-onboarding) sonra Unity uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır. Başlamadan önce şunları kontrol edin: 1. [Adapty Unity SDK](sdk-installation-unity) 3.14.0 veya üzeri sürümünü yüklediğinizden emin olun. 2. Bir [onboarding oluşturduğunuzdan](create-onboarding) emin olun. 3. Onboarding'i bir [placement](placements)'a eklediğinizden emin olun. ## Onboarding'i alın ve görünüm oluşturun \{#fetch-onboarding-and-create-view\} No-code builder'ımızla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın alıp göstermesi gereken bir yapılandırma içeren konteyner olarak saklanır. Bu konteyner, hangi içeriğin görüneceği, nasıl sunulacağı ve kullanıcı etkileşimlerinin (quiz cevapları veya form girişleri gibi) nasıl işleneceği dahil tüm deneyimi yönetir. Konteyner aynı zamanda analitik olaylarını otomatik olarak takip eder; bu sayede ayrıca görüntüleme takibi yapmanız gerekmez. En iyi performans için, kullanıcılara göstermeden önce görsellerin indirilmesine yeterli zaman tanımak amacıyla onboarding yapılandırmasını erken alın. Onboarding almak için `GetOnboarding` metodunu kullanın: ```csharp showLineNumbers Adapty.GetOnboarding("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.</p><p>Yerel ayar kodları ve bunların kullanımı hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](flutter-localizations-and-locale-codes) sayfasına bakın.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye erişmesini sağladığı için bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, dolayısıyla ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında korunduğunu ve yalnızca uygulama yeniden yüklendiğinde ya da manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı almak için CDN, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garantilemek için tasarlanmıştır.</p> | | **loadTimeout** | varsayılan: 5 sn | <p>Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.</p><p>Nadir durumlarda bu metodun `loadTimeout` ile belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.</p> | Yanıt parametreleri: | Parametre | Açıklama | |:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikler içeren bir [`AdaptyOnboarding`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_onboarding.html) nesnesi. | Onboarding'i aldıktan sonra `CreateOnboardingView` metodunu çağırın. :::warning `CreateOnboardingView` metodunun sonucu yalnızca bir kez kullanılabilir. Tekrar kullanmanız gerekiyorsa `CreateOnboardingView` metodunu yeniden çağırın. Yeniden oluşturmadan iki kez çağırmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```csharp showLineNumbers AdaptyUI.CreateOnboardingView(onboarding, (view, error) => { // handle the result }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |:---------------| :------------- |:-----------------------------------------------------------------------------| | **onboarding** | zorunlu | İstenen onboarding için görünüm elde etmek amacıyla kullanılan `AdaptyOnboarding` nesnesi. | | **externalUrlsPresentation** | <p>isteğe bağlı</p><p>varsayılan: `InAppBrowser`</p> | <p>Onboarding'deki bağlantıların nasıl açıldığını kontrol eder. Mevcut seçenekler:</p><p>- `AdaptyWebPresentation.InAppBrowser` - Bağlantıları uygulama içi tarayıcıda açar (varsayılan)</p><p>- `AdaptyWebPresentation.ExternalBrowser` - Bağlantıları cihazın harici tarayıcısında açar</p><p>Kullanım örnekleri için [Onboarding'lerde bağlantıların nasıl açıldığını özelleştirme](unity-present-onboardings#customize-how-links-open-in-onboardings) sayfasına bakın.</p> | Onboarding'i ve görünüm yapılandırmasını başarıyla yükledikten sonra [mobil uygulamanızda gösterebilirsiniz](unity-present-onboardings). ## Varsayılan kitle onboarding'i ile onboarding almayı hızlandırın \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Genellikle onboarding'ler neredeyse anında alınır, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, onboarding almak istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir onboarding göstermek isteyebilirsiniz. Bunu çözmek için, **Tüm Kullanıcılar** kitlesi için belirtilen placement'ın onboarding'ini alan `GetOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Onboarding Alma](#fetch-onboarding) bölümünde ayrıntılı olarak açıklandığı şekilde `getOnboarding` metoduyla onboarding almak olduğunu anlamak çok önemlidir. :::warning `GetOnboardingForDefaultAudience` yerine `GetOnboarding` kullanmayı düşünün; ikincisinin önemli sınırlamaları vardır: - **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorun yaratabilir; geriye dönük uyumlu tasarımlar yapmanızı veya eski sürümlerin yanlış görüntülenebileceğini kabul etmenizi gerektirir. - **Kişiselleştirme yok**: Yalnızca "Tüm Kullanıcılar" kitlesi için içerik gösterir; ülke, attribution veya özel özniteliklere dayalı hedeflemeyi ortadan kaldırır. Kullanım durumunuzda daha hızlı alma bu dezavantajlardan daha önemli ise, aşağıda gösterildiği gibi `GetOnboardingForDefaultAudience` kullanın. Aksi takdirde [yukarıda](#fetch-onboarding) açıklandığı gibi `GetOnboarding` kullanın. ::: ```csharp showLineNumbers Adapty.GetOnboardingForDefaultAudience("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` Parametreler: | Parametre | Zorunluluk | Açıklama | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. | | **locale** | <p>isteğe bağlı</p><p>varsayılan: `en`</p> | <p>Onboarding yerelleştirmesinin tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olmalıdır. İlk alt etiket dil için, ikincisi bölge içindir.</p><p></p><p>Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.</p> | | **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` | <p>SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye erişmesini sağladığı için bu seçeneği öneririz.</p><p></p><p>Ancak kullanıcılarınızın kararsız internet bağlantısıyla uğraştığını düşünüyorsanız, önbelleğe alınmış veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünebilirsiniz. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, dolayısıyla ağ isteklerinden kaçınmak için oturum sırasında kullanmak güvenlidir.</p><p></p><p>Önbelleğin uygulama yeniden başlatıldığında korunduğunu ve yalnızca uygulama yeniden yüklendiğinde ya da manuel temizleme yapıldığında silindiğini unutmayın.</p><p></p><p>Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı almak için CDN, CDN'e erişilemediği durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garantilemek için tasarlanmıştır.</p> | --- # File: unity-present-onboardings --- --- title: "Unity SDK'da onboarding sunma" description: "Daha fazla dönüşüm elde etmek için onboarding'leri etkili biçimde nasıl sunacağınızı öğrenin." --- Builder'ı kullanarak bir onboarding özelleştirdiyseniz, onu kullanıcıya göstermek için Unity uygulama kodunuzda ayrıca render etmeniz gerekmez. Bu tür bir onboarding, hem onboarding içinde neyin gösterileceğini hem de nasıl gösterileceğini zaten içerir. Başlamadan önce şunları doğrulayın: 1. [Adapty Unity SDK](sdk-installation-unity) 3.14.0 veya daha yeni bir sürümü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Bir onboarding görüntülemek için `CreateOnboardingView` metoduyla oluşturulan `view` üzerinde `view.Present()` metodunu kullanın. Her `view` yalnızca bir kez kullanılabilir. Paywall'ı tekrar görüntülemeniz gerekirse, yeni bir `view` örneği oluşturmak için `CreateOnboardingView` metodunu bir kez daha çağırın. :::warning `view`'ı yeniden oluşturmadan tekrar kullanmak `AdaptyUIError.viewAlreadyPresented` hatasına yol açabilir. ::: ```csharp showLineNumbers title="Unity" view.Present((presentError) => { if (presentError != null) { // handle the error } }; ``` ## iOS sunum stilini yapılandırma \{#configure-ios-presentation-style\} `Present()` metoduna `iosPresentationStyle` parametresini geçerek onboarding'in iOS'ta nasıl sunulacağını yapılandırın. Parametre `AdaptyUIIOSPresentationStyle.FullScreen` (varsayılan) veya `AdaptyUIIOSPresentationStyle.PageSheet` değerlerini kabul eder. ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` ## Onboarding'lerde bağlantıların nasıl açılacağını özelleştirin \{#customize-how-links-open-in-onboardings\} :::important Onboarding'lerde bağlantıların nasıl açılacağını özelleştirme özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir. ::: Varsayılan olarak, onboarding'lerdeki bağlantılar uygulama içi tarayıcıda açılır; bu sayede uygulamalar arasında geçiş yapmadan web sayfaları doğrudan uygulamanız içinde gösterilir. Bağlantıları bunun yerine harici bir tarayıcıda açmak için `CreateOnboardingView` metoduna `AdaptyWebPresentation.ExternalBrowser` değerini geçin: ```csharp showLineNumbers title="Unity" AdaptyUI.CreateOnboardingView( onboarding, AdaptyWebPresentation.ExternalBrowser, // default — InAppBrowser (view, error) => { if (error != null) { // handle the error return; } // present the onboarding view view.Present((presentError) => { if (presentError != null) { // handle the error } }); } ); ``` Mevcut seçenekler: - `AdaptyWebPresentation.InAppBrowser` - Bağlantıları uygulama içi tarayıcıda açar (varsayılan) - `AdaptyWebPresentation.ExternalBrowser` - Bağlantıları cihazın harici tarayıcısında açar --- # File: unity-handling-onboarding-events --- --- title: "Unity SDK'da onboarding olaylarını işleme" description: "Adapty kullanarak Unity'de onboarding ile ilgili olayları işleyin." --- Başlamadan önce şunların sağlandığından emin olun: 1. [Adapty Unity SDK](sdk-installation-unity) 3.14.0 veya daha yeni bir sürümünü yüklediniz. 2. [Bir onboarding oluşturdunuz](create-onboarding). 3. Onboarding'i bir [placement](placements)'a eklediniz. Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar oluşturur. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz. Unity uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyOnboardingsEventsListener` arayüzünü uygulayın. ## Özel eylemler \{#custom-actions\} Builder'da bir butona **custom** (özel) eylem ekleyip bir ID atayabilirsiniz. <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu ID'yi kodunuzda kullanarak özel bir eylem olarak işleyebilirsiniz. Örneğin, kullanıcı **Login** veya **Allow notifications** gibi özel bir butona dokunduğunda, `OnboardingViewOnCustomAction` metodu `actionId` parametresiyle tetiklenir; bu parametre builder'daki **Action ID** değerine karşılık gelir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz. Onboarding olaylarını yönetmek için `AdaptyOnboardingsEventsListener` arayüzünü uygulayın: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { void Start() { Adapty.SetOnboardingsEventsListener(this); } public void OnboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { if (actionId == "allowNotifications") { // request notification permissions } } public void OnboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error ) { // handle errors } // Implement other required interface methods (see examples below) } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## Onboarding'i kapatma \{#closing-onboarding\} Onboarding, kullanıcı **Close** eylemi atanmış bir butona dokunduğunda kapanmış sayılır. <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important Kullanıcı onboarding'i kapattığında ne olacağını kendiniz yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in görüntülenmesini durdurmanız gerekir. ::: Sınıfınızda `OnboardingViewOnCloseAction` metodunu uygulayın: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { view.Dismiss((error) => { if (error != null) { // handle the error } }); } // ... other interface methods } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## Bir paywall açma \{#opening-a-paywall\} :::tip Onboarding içinde bir paywall açmak istiyorsanız bu olayı işleyin. Paywall kapatıldıktan sonra açmak istiyorsanız daha doğrudan bir yol var: [`OnboardingViewOnCloseAction`](#closing-onboarding) olayını işleyin ve olay verisine dayanmadan paywall'ı açın. ::: Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, aksiyon ID'sini bir paywall placement ID'siyle eşit kılmaktır. Bu sayede `OnboardingViewOnPaywallAction` sonrasında, placement ID'yi kullanarak paywall'ı hemen alıp açabilirsiniz. iOS'ta aynı anda ekranda yalnızca bir görünüm (paywall veya onboarding) gösterilebilir. Onboarding'in üzerine bir paywall sunarsanız, arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışırsanız bunun yerine paywall kapanır ve onboarding görünür kalır. Bunu önlemek için paywall sunmadan önce her zaman onboarding görünümünü kapatın. ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { // Dismiss onboarding before presenting paywall view.Dismiss((dismissError) => { if (dismissError != null) { // handle the error return; } Adapty.GetPaywall(actionId, (paywall, error) => { if (error != null) { // handle the error return; } AdaptyUI.CreatePaywallView(paywall, (paywallView, createError) => { if (createError != null) { // handle the error return; } paywallView.Present((presentError) => { if (presentError != null) { // handle the error } }); }); }); }); } // ... other interface methods } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## Onboarding yüklemesinin tamamlanması \{#finishing-loading-onboarding\} Onboarding yüklemesi tamamlandığında `OnboardingViewDidFinishLoading` metodunu uygulayın: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta ) { // handle loading completion } // ... other interface methods } ``` <Details> <summary>Olay örneği (Genişletmek için tıklayın)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## Navigasyonu izleme \{#tracking-navigation\} `OnboardingViewOnAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır. `analyticsEvent` nesnesi aşağıdaki türlerden biri olabilir: | Tür | Açıklama | |------------|-------------| | `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | Onboarding yüklendiğinde | | `AdaptyOnboardingsAnalyticsEventScreenPresented` | Herhangi bir ekran gösterildiğinde | | `AdaptyOnboardingsAnalyticsEventScreenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `ElementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `Reply` (kullanıcının yanıtı) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. | | `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | İkinci ekran gösterildiğinde | | `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | Kullanıcının e-postası giriş alanı aracılığıyla toplandığında tetiklenir | | `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | Kullanıcı `final` ID'li bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa [son ekrana `final` ID'yi atayın](design-onboarding). | | `AdaptyOnboardingsAnalyticsEventUnknown` | Tanınmayan olay türleri için. `Name` (bilinmeyen olayın adı) ve `meta` (ek meta veriler) içerir | Her olay şu alanları içeren `meta` bilgisini barındırır: | Alan | Açıklama | |------------|-------------| | `OnboardingId` | Onboarding akışının benzersiz tanımlayıcısı | | `ScreenClientId` | Mevcut ekranın tanımlayıcısı | | `ScreenIndex` | Mevcut ekranın akıştaki konumu | | `ScreensTotal` | Akıştaki toplam ekran sayısı | Analitik olaylarını izleme amacıyla nasıl kullanabileceğinize dair bir örnek: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent analyticsEvent ) { switch (analyticsEvent) { case AdaptyOnboardingsAnalyticsEventOnboardingStarted: // track onboarding start TrackEvent("onboarding_started", meta); break; case AdaptyOnboardingsAnalyticsEventScreenPresented: // track screen presentation TrackEvent("screen_presented", meta); break; case AdaptyOnboardingsAnalyticsEventScreenCompleted screenCompleted: // track screen completion with user response TrackEvent("screen_completed", meta, screenCompleted.ElementId, screenCompleted.Reply); break; case AdaptyOnboardingsAnalyticsEventOnboardingCompleted: // track successful onboarding completion TrackEvent("onboarding_completed", meta); break; case AdaptyOnboardingsAnalyticsEventUnknown unknownEvent: // handle unknown events TrackEvent(unknownEvent.Name, meta); break; // handle other cases as needed } } // ... other interface methods } ``` :::note `TrackEvent` metodu, analitik verilerini tercih ettiğiniz analitik servisine göndermek için kendiniz uygulamanız gereken bir yer tutucudur. ::: <Details> <summary>Olay örnekleri (Genişletmek için tıklayın)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: unity-onboarding-input --- --- title: "Unity SDK'da onboarding verilerini işleme" description: "Adapty SDK ile Unity uygulamanızdaki onboarding verilerini kaydedin ve kullanın." --- Kullanıcılarınız bir quiz sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `OnboardingViewOnStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz. Sınıfınızda `OnboardingViewOnStateUpdatedAction` metodunu uygulayın: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { switch (@params) { case AdaptyOnboardingsSelectParams selectParams: // handle single selection break; case AdaptyOnboardingsMultiSelectParams multiSelectParams: // handle multiple selections break; case AdaptyOnboardingsInputParams inputParams: // handle text input break; case AdaptyOnboardingsDatePickerParams datePickerParams: // handle date selection break; } } // ... other interface methods } ``` Parametreler şunlardır: | Parametre | Açıklama | |----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `elementId` | Giriş öğesi için benzersiz bir tanımlayıcı. Soruları yanıtlarla ilişkilendirmek için kullanabilirsiniz. | | `@params` | Kullanıcının girdi veri nesnesi. Aşağıdaki türlerden biri olabilir. | | `AdaptyOnboardingsSelectParams` | Seçeneklerden tek seçim. `Id`, `Value`, `Label` içerir. | | `AdaptyOnboardingsMultiSelectParams` | Seçeneklerden çoklu seçim. `Params` listesi içerir (her biri `Id`, `Value`, `Label` ile)<br/>• `input`: `type`, `value` içeren nesne<br/>• `datePicker`: `day`, `month`, `year` içeren nesne | | `AdaptyOnboardingsInputParams` | Metin giriş alanı. `AdaptyOnboardingsTextInput`, `AdaptyOnboardingsEmailInput` veya `AdaptyOnboardingsNumberInput` olabilen `Input` içerir. | | `AdaptyOnboardingsDatePickerParams` | Tarih seçimi. Null olabilen `Day`, `Month`, `Year` içerir. | <Details> <summary>Kaydedilen veri örnekleri (uygulamanızda farklılık gösterebilir)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## Kullanım senaryoları \{#use-cases\} ### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\} Giriş verilerini kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, eylemi işlerken giriş verisiyle [kullanıcı profilini güncellemeniz](unity-setting-user-attributes) gerekir. Örneğin, kullanıcılara `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak ayarlamak istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmelerini de istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { if (@params is AdaptyOnboardingsInputParams inputParams) { var builder = new AdaptyProfileParameters.Builder(); switch (elementId) { case "name": if (inputParams.Input is AdaptyOnboardingsTextInput textInput) { builder.SetFirstName(textInput.Value); } break; case "email": if (inputParams.Input is AdaptyOnboardingsEmailInput emailInput) { builder.SetEmail(emailInput.Value); } break; } Adapty.UpdateProfile(builder.Build(), (error) => { if (error != null) { // handle the error } }); } } // ... other interface methods } ``` ### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\} Onboarding'lerdeki quizleri kullanarak, kullanıcılara onboarding'i tamamladıktan sonra gösterdiğiniz paywallları da özelleştirebilirsiniz. Örneğin, kullanıcılara spor deneyimleri hakkında soru sorarak farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz. 1. Onboarding builder'da bir [quiz ekleyin](onboarding-quizzes) ve seçeneklerine anlamlı ID'ler atayın. 2. Quiz yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel attribute'lar ayarlayın](unity-setting-user-attributes). ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { if (@params is AdaptyOnboardingsSelectParams selectParams) { var builder = new AdaptyProfileParameters.Builder(); switch (elementId) { case "experience": // set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.SetCustomStringAttribute("experience", selectParams.Value); break; } Adapty.UpdateProfile(builder.Build(), (error) => { if (error != null) { // handle the error } }); } } // ... other interface methods } ``` 3. Her özel attribute değeri için [segment oluşturun](segments). 4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin. 5. Uygulama kodunuzda placement için bir [paywall görüntüleyin](unity-paywalls). Onboarding'inizde bir paywall açan buton varsa, paywall kodunu [bu butonun eylemine yanıt olarak](unity-handling-onboarding-events#opening-a-paywall) uygulayın. --- # File: unity-sdk-call-order --- --- title: "Unity SDK'da çağrı sırası" description: "Adapty SDK metodlarını doğru sırayla çağırarak premium erişim kaybını, eksik attribution'ı ve aralıklı #2002 hatalarını önleyin." --- `Adapty.Activate()` tamamlanmadan diğer hiçbir Adapty SDK metodunu çağırmamalısınız. Tamamlanma callback'i tetiklenmeden SDK'nın herhangi bir durumu olmaz. `Activate()` tamamlanmadan veya onunla paralel olarak yapılan her çağrı [`#2002 notActivated`](unity-handle-errors#custom-network-codes) hatasıyla başarısız olur. Uygulamanız kullanıcıların kimliğini doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, o noktada `Adapty.Identify()` çağrısı yapın. `Identify` geri çağrısı tetiklenene kadar kullanıcı eylemine bağlı metodları çağırmayın. Bu metodlarla yarışan çağrılar ya [`#3006 profileWasChanged`](unity-handle-errors#custom-network-codes) hatasıyla başarısız olur ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP kimlikleri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcı kimlik doğrulaması yapmıyorsa `Identify` çağrısını atlayın ve anonim profille çalışmaya devam edin. MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `Adapty.Activate` çağrısından önce bunları başlatın ve UID callback'lerini bekleyin. Aksi takdirde MMP kimliği, kısa süreli anonim bir profile atanır ve bu kimlik tanımlanmış profile her zaman aktarılamayabilir. AppsFlyer'a özgü ayrıntılar için [AppsFlyer](appsflyer) sayfasına bakın. ## Doğru sıralama \{#the-correct-order\} Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve bir MMP ya da analitik SDK kullanıp kullanmadığınız. - **2. ve 5. adımlar**: Her uygulama için zorunludur. Önce SDK'yı etkinleştirin, ardından SDK metodlarını çağırın. - **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK (AppsFlyer, Adjust, Branch, PostHog) entegre ediyorsanız gereklidir. - **4. adım**: Yalnızca uygulamanız kullanıcıları doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir. Uygulama başlangıcında müşteri kullanıcı kimliğiniz varsa, doğrudan `Activate()` içine aktarın (adım 2a). Bu yol hiçbir zaman anonim profil oluşturmaz, dolayısıyla adım 4 gerekli değildir. | Adım | Çağrı | Ne Zaman | Notlar | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlatma, ilk önce | MMP'nin UID callback'ini bekleyin, örneğin `getAppsFlyerId`. | | 2a | `SetCustomerUserId` ayarlanmış builder ile `Adapty.Activate(builder.Build(), ...)` | Adım 1'den sonra, uygulama başlatma sırasında, müşteri kullanıcı kimliğine sahipseniz | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. | | 2b | `SetCustomerUserId` olmadan `Adapty.Activate(builder.Build(), ...)` | Adım 1'den sonra, uygulama başlatma sırasında, müşteri kullanıcı kimliğiniz yoksa (veya hiç toplamıyorsanız) | Adapty anonim bir profil oluşturur. | | 3 | Her MMP için `Adapty.SetIntegrationIdentifier(key, value, callback)` | Adım 2'den sonra, herhangi bir kullanıcı eylemi çağrısından önce | MMP kimliklerinin doğru profile düşmesi için gereklidir. | | 4 | `Adapty.Identify("YOUR_USER_ID", callback)` | Adım 3'ten sonra (veya MMP yoksa adım 2'den sonra), adım 5'ten önce — yalnızca kimlik doğrulama ile 2b yolunda | Tamamlama callback'ini bekleyin. `Identify` sırasında yapılan eş zamanlı çağrılar `#3006 profileWasChanged` hatası üretir. | | 5 | `GetPaywall`, `GetPaywallProducts`, `RestorePurchases`, `MakePurchase`, `UpdateAttribution`, `UpdateProfile` | `Identify` çağırıyorsanız adım 4'ten sonra; değilse adım 3'ten sonra (veya MMP yoksa adım 2'den sonra) | Bu çağrılar kararlı bir profile ihtiyaç duyar. | :::important Bu adımları atlamak; geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitle için döndürülen paywallara yol açar. ::: ## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\} Kullanıcılar bir web checkout'unda (Stripe, Paddle) satın alma yapıp ardından native uygulamayı yüklerse, cihazın ilk `Activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Uygulama başlatılmadan önce customer user ID'yi çözümleyebiliyorsanız (auth akışınızdan veya install referrer'dan), bunu doğrudan `Activate()` içine aktarın. Aksi takdirde web satın alımı, `Identify("YOUR_USER_ID")` ve ardından `RestorePurchases` çağrısı yapılana kadar cihazda görünmez. Her web checkout'uyla gönderilecek metadata için şu sayfalara bakın: - [Stripe](stripe) - [Paddle](paddle) --- # File: unity-optimize-paywall-fetching --- --- title: "Unity SDK'da paywall getirimini optimize edin" description: "Adapty paywalllerini güvenilir şekilde getirin: Unity için zamanlama, önbellekleme ve yedek paywall kalıpları." --- Unity'de güvenilir bir paywall getirimi üç şeyi başarır: hızlı render eder, kitleye yönelik doğru paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz şekilde yedek paywall'a geçer. Aşağıdaki kurallar bu hedefe ulaşmak için zamanlama, önbellekleme ve yedek paywall kalıplarını kapsar. :::tip Bu kurallar, `Adapty.Activate()` ve `Adapty.Identify()` işlemlerinin zaten tamamlandığını varsayar. Bkz. [Unity SDK'da çağrı sırası](unity-sdk-call-order). ::: ## Kurallar ve tuzaklar \{#rules-and-pitfalls\} | Bunu yapın | Bunu yapmayın | Neden | |---|---|---| | Göstermek üzere olduğunuz placement'ı yükleyin. | Tüm placement'ları uygulama açılışında eş zamanlı olarak önceden yükleyin. | Toplu önceden yükleme, ana iş parçacığını bloke eder ve yoğunluk sırasında siyah ekrana neden olur. | | `GetPaywall`'ı attribution çözümlendikten sonra çağırın — örneğin `Activate`'den 1–2 saniye sonra veya `OnLoadLatestProfile` tetiklendikten sonra. | `GetPaywall`'ı `Awake()` içinde çağırın. | Attribution henüz gelmemiştir. Paywall varsayılan kitleye göre çözümlenir ve segmentlerle ASA kişiselleştirmesini sessizce atlar. | | Her placement için bir `loadTimeout` ayarlayın ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `GetPaywall`'ın sonucunu süresiz olarak bekleyin. | Zaman aşımı olmadan, zayıf bağlantıdaki kullanıcılar ağ çözümlenene kadar boş ekran görür veya uygulamayı kapatır. | `fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall'ları ve ürünleri getir](fetch-paywalls-and-products-unity) sayfasına, doğru placement'ı seçmek için ise [Placement'lar](placements) sayfasına bakın. ## Zayıf bağlantı için ayarlama \{#tune-for-poor-connectivity\} Sürekli zayıf bağlantı yaşanan pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunları olan bölgeler): - İlk fetch dışındaki tüm fetch işlemlerinde `fetchPolicy` değerini `AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad` olarak ayarlayın. - Adapty Kontrol Paneli'nde her placement için bir [yedek paywall](fallback-paywalls) yapılandırın. - `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalla geçin. - Paywall gösterimini `GetProfile` çağrısına bağlamayın. `GetPaywall` işlemini bağımsız olarak çağırın; bu sayede yavaş bir profil yüklemesi arayüzü engellemez. --- # File: unity-test --- --- title: "Unity SDK'da Test Et ve Yayınla" description: "Adapty SDK ile Unity uygulamanızı nasıl test edip yayınlayacağınızı öğrenin." --- Adapty SDK'yı Unity uygulamanıza entegre ettiyseniz, her şeyin doğru kurulduğunu ve satın almaların hem iOS hem Android platformlarında beklediğiniz gibi çalıştığını test etmek isteyeceksiniz. Bu süreç, hem SDK entegrasyonunun hem de Apple'ın sandbox ortamı ile Google Play'in test ortamında gerçek satın alma akışının test edilmesini kapsar. ## Uygulamanızı test edin \{#test-your-app\} Uygulama içi satın almalarınızı kapsamlı şekilde test etmek için platforma özel test kılavuzlarımıza bakın: [iOS test kılavuzu](test-purchases-in-sandbox) ve [Android test kılavuzu](testing-on-android). ## Yayına hazırlanın \{#prepare-for-release\} Uygulamanızı mağazaya göndermeden önce, aşağıdakileri doğrulamak için [Yayın kontrol listesi](release-checklist)'ni takip edin: - Mağaza bağlantısı ve sunucu bildirimleri yapılandırılmış - Satın almalar tamamlanıyor ve Adapty'e bildiriliyor - Erişim doğru şekilde kilidi açılıyor ve geri yükleniyor - Gizlilik ve inceleme gereksinimleri karşılanmış --- # File: InvalidProductIdentifiers-unity --- --- title: "Unity SDK'da Code-1000 noProductIDsFound Hatasının Çözümü" description: "Adapty'de abonelikleri yönetirken geçersiz ürün tanımlayıcısı hatalarını çözün." --- 1000 kodlu `noProductIDsFound` hatası, paywall'da talep ettiğiniz ürünlerin App Store'da listelenmiş olmasına rağmen satın almaya açık olmadığı anlamına gelir. Bu hata bazen `InvalidProductIdentifiers` uyarısıyla birlikte görünebilir. Uyarı tek başına çıkıyorsa ve hata yoksa görmezden gelebilirsiniz. `noProductIDsFound` hatasıyla karşılaşıyorsanız sorunu çözmek için şu adımları izleyin: ## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin. 2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın. <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın. <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın. 5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın. ## Adım 2. Ürünleri kontrol edin \{#step-3-check-products\} 1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne geçin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümünde göreceksiniz. 3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Tablodaki ürün ID'sini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesindekiyle karşılaştırın. ID'ler eşleşmiyorsa ürün ID'sini tablodan kopyalayın ve Adapty Kontrol Paneli'nde bu ID ile [bir ürün oluşturun](create-product). <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\} 1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** bölümüne inin ve gerekli tüm ülke ve bölgelerin listelendiğini doğrulayın. <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\} 1. **App Store Connect**'teki **Monetization** → **Subscriptions** bölümüne gidin. <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Abonelik grubu adına tıklayın. 3. Test ettiğiniz ürünü seçin. <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** bölümüne inin ve **Current Pricing for New Subscribers** kısmını genişletin. <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Gerekli tüm fiyatların listelendiğinden emin olun. <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adım 5. Uygulamanın ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. **App Store Connect**](https://appstoreconnect.apple.com/) ana sayfasında **Business** seçeneğine tıklayın. <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Şirketinizin adını seçin. 3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** bölümlerinin tümünün **Active** olarak göründüğünü doğrulayın. <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayına alabilirsiniz. ## Adım 6. Ürün takılı kaldıysa yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\} 1–5 arası adımların hepsi geçiyor olabilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — ancak SDK yine de `1000 noProductIDsFound` hatası döndürüyor olabilir. Bu durumda ürün, Apple'ın kayıt defterinde takılı kalmış olabilir. Apple'ın ürün kayıt defteri zaman zaman, bir ürünün App Store Connect arayüzünde görünmesine karşın StoreKit arama yoluna açık olmadığı bir duruma girebilir. Ürünü App Store Connect'te silin ve aynı ürün kimliğiyle yeniden oluşturun. Yeniden oluşturmanın ardından yayılımın tamamlanması için 24 saate kadar bekleyin. --- # File: cantMakePayments-unity --- --- title: "Unity SDK'da Code-1003 cantMakePayment hatasının çözümü" description: "Adapty'de abonelikleri yönetirken oluşan ödeme hatalarını çözün." --- 1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir. `cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir: - Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın. - Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın. ## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\} | Sorun | Çözüm | |------------------------------|------------------------------------------------------------------------------------------------------------------------------| | Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın | | Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin | | Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın | ## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\} Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir. Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz. --- # File: migration-to-unity-sdk-314 --- --- title: "Adapty Unity SDK'yı v3.14'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Unity SDK v3.14'e geçin." --- Adapty SDK 3.14.0, bazı geliştirmeler getiren büyük bir sürümdür. Bu geliştirmeler sizin tarafınızdan bazı taşıma adımları gerektirebilir: 1. Paywall olayları için ayrı event listener. 2. `AdaptyUI.CreateView`'i `AdaptyUI.CreatePaywallView` ve ilgili metodlara yeniden adlandırın. 3. `MakePurchase` metodunu bireysel parametreler yerine `AdaptyPurchaseParameters` kullanacak şekilde güncelleyin. 4. `SetFallbackPaywalls`'u `SetFallback` metoduyla değiştirin. 5. Paywall özellik erişimini `AdaptyPlacement` kullanacak şekilde güncelleyin. 6. Remote config erişimini `AdaptyRemoteConfig` nesnesi kullanacak şekilde güncelleyin. 7. `AdaptyPaywall` modelinde `VendorProductIds`'i `ProductIdentifiers` ile değiştirin. 8. `GetPaywall` fetch policy'sini `AdaptyFetchPolicy` kullanacak şekilde güncelleyin. ## Paywall olayları için ayrı olay dinleyicisi \{#separate-event-listener-for-paywall-events\} [Paywall Builder](adapty-paywall-builder) ile tasarlanmış paywallları görüntülüyorsanız, paywall görünüm olayları artık özel `AdaptyPaywallsEventsListener` arayüzünü ve `SetPaywallsEventsListener` metodunu kullanmaktadır. `AdaptyEventListener` arayüzü ise profil güncellemeleri ve kurulum detayları için kullanılmaya devam etmektedir. ```diff showLineNumbers using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, - AdaptyEventListener { + AdaptyEventListener, + AdaptyPaywallsEventsListener { void Start() { Adapty.SetEventListener(this); + Adapty.SetPaywallsEventsListener(this); } // AdaptyEventListener methods public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } + // AdaptyPaywallsEventsListener methods + // Implement paywall event handlers here } ``` [Paywall olaylarını işleme hakkında daha fazla bilgi edinin](unity-handling-events). ## Görünüm oluşturma ve sunum metodlarını yeniden adlandırın \{#rename-view-creation-and-presentation-methods\} Görünüm oluşturma ve sunum metodları yeniden adlandırıldı: ```diff showLineNumbers using AdaptySDK; - AdaptyUI.CreateView(paywall, parameters, (view, error) => { + AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if (error != null) { // handle the error return; } - AdaptyUI.PresentView(view, (error) => { + AdaptyUI.PresentPaywallView(view, (error) => { // handle the error }); }); } ``` Benzer şekilde, kapatma metodu da yeniden adlandırıldı: ```diff showLineNumbers - AdaptyUI.DismissView(view, (error) => { + AdaptyUI.DismissPaywallView(view, (error) => { // handle the error }); ``` ## MakePurchase yöntemini güncelleme \{#update-makepurchase-method\} `MakePurchase` yöntemi artık ayrı `subscriptionUpdateParams` ve `isOfferPersonalized` argümanları yerine `AdaptyPurchaseParameters` kullanıyor. Bu, daha iyi tür güvenliği sağlar ve gelecekte satın alma parametrelerinin genişletilebilmesine olanak tanır. ```diff showLineNumbers using AdaptySDK; void MakePurchase( AdaptyPaywallProduct product, AdaptySubscriptionUpdateParameters subscriptionUpdate, bool? isOfferPersonalized ) { - Adapty.MakePurchase(product, subscriptionUpdate, isOfferPersonalized, (result, error) => { + var parameters = new AdaptyPurchaseParametersBuilder() + .SetSubscriptionUpdateParams(subscriptionUpdate) + .SetIsOfferPersonalized(isOfferPersonalized) + .Build(); + + Adapty.MakePurchase(product, parameters, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successful purchase break; default: break; } }); } ``` Ek parametreye ihtiyaç duyulmuyorsa şunu kullanabilirsiniz: ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { // handle purchase result }); } ``` ## Yedek paywall yöntemini güncelleme \{#update-fallback-method\} :::important Unity SDK 3.14 sürümüne yükseltirken, Adapty Kontrol Paneli'nden yeni yedek dosyaları indirip projenizdeki mevcut dosyaların yerine koymanız gerekecektir. ::: Yedekleri ayarlama yöntemi güncellendi. `SetFallbackPaywalls` yöntemi `SetFallback` olarak yeniden adlandırıldı: ```diff showLineNumbers using AdaptySDK; void SetFallBackPaywalls() { #if UNITY_IOS var assetId = "adapty_fallback_ios.json"; #elif UNITY_ANDROID var assetId = "adapty_fallback_android.json"; #else var assetId = ""; #endif - Adapty.SetFallbackPaywalls(assetId, (error) => { + Adapty.SetFallback(assetId, (error) => { // handle the error }); } ``` Son kod örneğini [Unity'de yedek paywall kullanımı](unity-use-fallback-paywalls) sayfasında inceleyebilirsiniz. ## Paywall özellik erişimini güncelleme \{#update-paywall-property-access\} Aşağıdaki özellikler `AdaptyPaywall`'dan `AdaptyPlacement`'a taşındı: ```diff showLineNumbers using AdaptySDK; void ProcessPaywall(AdaptyPaywall paywall) { - var abTestName = paywall.ABTestName; - var audienceName = paywall.AudienceName; - var revision = paywall.Revision; - var placementId = paywall.PlacementId; + var abTestName = paywall.Placement.ABTestName; + var audienceName = paywall.Placement.AudienceName; + var revision = paywall.Placement.Revision; + var placementId = paywall.Placement.Id; } ``` ## Remote config erişimini güncelleme \{#update-remote-config-access\} Remote config özellikleri, daha iyi bir yapı için `AdaptyRemoteConfig` nesnesi altında yeniden düzenlendi: ```diff showLineNumbers using AdaptySDK; void ProcessRemoteConfig(AdaptyPaywall paywall) { - var remoteConfigString = paywall.RemoteConfigString; - var locale = paywall.Locale; - var remoteConfigDict = paywall.RemoteConfig; + var remoteConfigString = paywall.RemoteConfig.Data; + var locale = paywall.RemoteConfig.Locale; + var remoteConfigDict = paywall.RemoteConfig.Dictionary; } ``` ## AdaptyPaywall model kullanımını güncelleme \{#update-adaptypaywall-model-usage\} `VendorProductIds` özelliği kullanımdan kaldırılmış olup yerine `ProductIdentifiers` geçmiştir. Yeni özellik, basit string'ler yerine `AdaptyProductIdentifier` nesneleri döndürerek daha yapılandırılmış ürün bilgisi sağlar. ```diff showLineNumbers using AdaptySDK; void ProcessPaywallProducts(AdaptyPaywall paywall) { - var productIds = paywall.VendorProductIds; - foreach (var vendorId in productIds) { - // use vendorId - } + var productIdentifiers = paywall.ProductIdentifiers; + foreach (var productId in productIdentifiers) { + var vendorId = productId.VendorProductId; + // use vendorId + } } ``` `AdaptyProductIdentifier` nesnesi, `VendorProductId` özelliği aracılığıyla satıcı ürün kimliğine erişim sağlar; aynı işlevselliği korurken gelecekteki geliştirmeler için daha iyi bir yapı sunar. ## GetPaywall fetch policy'sini güncelleme \{#update-getpaywall-fetch-policy\} `GetPaywall` metodundaki `fetchPolicy` parametre türü `AdaptyPaywallFetchPolicy`'den `AdaptyPlacementFetchPolicy`'ye değiştirildi. Bu değişiklik, SDK genelinde fetch policy kullanımını birleştiriyor. ```diff showLineNumbers using AdaptySDK; void GetPaywall(string placementId) { - Adapty.GetPaywall(placementId, AdaptyPaywallFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => { + Adapty.GetPaywall(placementId, AdaptyPlacementFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => { // handle the result }); } ``` --- # File: migration-to-unity-sdk-34 --- --- title: "Adapty Unity SDK'yı v3.4'e Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Unity SDK v3.4'e geçiş yapın." --- Adapty SDK 3.4.0, sizin tarafınızdan geçiş adımları gerektiren iyileştirmeler sunan büyük bir sürümdür. ## Yedek paywall dosyalarını güncelleme \{#update-fallback-paywall-files\} Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin: 1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls). 2. Mobil uygulamanızdaki [mevcut yedek paywallları yeni dosyalarla değiştirin](unity-use-fallback-paywalls). ## Observer Mode uygulamasını güncelleme \{#update-implementation-of-observer-mode\} Observer Mode kullanıyorsanız, uygulamasını güncellediğinizden emin olun. Daha önce, işlemleri Adapty'ye bildirmek için farklı yöntemler kullanılıyordu. Yeni sürümde, hem Android hem de iOS'ta tutarlı biçimde `reportTransaction` yöntemi kullanılmalıdır. Bu yöntem, her işlemi açıkça Adapty'ye bildirir ve işlemin tanınmasını sağlar. Bir paywall kullanıldıysa, işlemi bununla ilişkilendirmek için variation ID'yi iletin. :::warning **İşlem bildirmeyi atlayın!** `reportTransaction` çağrısını yapmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez. ::: ```diff showLineNumbers - #if UNITY_ANDROID && !UNITY_EDITOR - Adapty.RestorePurchases((profile, error) => { - // handle the error - }); - #endif Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` --- # File: migration-to-unity330 --- --- title: "Adapty Unity SDK'yı v3.3'e Geçirme" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Unity SDK v3.3'e geçin." --- Adapty SDK 3.3.0, bazı iyileştirmeler getiren büyük bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir. 1. Adapty SDK v3.3.x sürümüne yükseltin. 2. Adapty SDK'nın Adapty ve AdaptyUI modüllerindeki birden fazla sınıf, özellik ve yöntem yeniden adlandırıldı. 3. Artık `SetLogLevel` yöntemi bir callback'i argüman olarak kabul etmektedir. 4. Artık `PresentCodeRedemptionSheet` yöntemi bir callback'i argüman olarak kabul etmektedir. 5. Paywall görünümünün oluşturulma şeklini değiştirin. 6. `GetProductsIntroductoryOfferEligibility` yöntemini kaldırın. 7. Yedek paywallları `Assets/StreamingAssets/` dizininde ayrı dosyalara (platform başına bir tane) kaydedin ve dosya adlarını `SetFallbackPaywalls` yöntemine iletin. 8. Satın alma işlemini güncelleyin. 9. Paywall Builder olaylarının işlenmesini güncelleyin. 10. Paywall Builder paywall hatalarının işlenmesini güncelleyin. 11. Adjust, Amplitude, AppMetrica, Appsflyer, Branch, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin. 13. Observer modu uygulamasını güncelleyin. 14. Unity eklentisi başlatmasını açık bir `Activate` çağrısıyla güncelleyin. ## Adapty Unity SDK'yı 3.3.x Sürümüne Yükseltin \{#upgrade-adapty-unity-sdk-to-33x\} Bu sürüme kadar Adapty SDK, uygulamanızda Adapty'nin düzgün çalışması için zorunlu olan temel SDK'ydi; AdaptyUI SDK ise yalnızca Adapty Paywall Builder kullanıyorsanız gerekli hale gelen isteğe bağlı bir SDK'ydı. 3.3.0 sürümüyle birlikte AdaptyUI SDK kullanımdan kaldırılmış ve AdaptyUI, Adapty SDK'ya bir modül olarak dahil edilmiştir. Bu değişiklikler nedeniyle AdaptyUI SDK'yı kaldırıp AdaptySDK'yı yeniden yüklemeniz gerekmektedir. 1. **AdaptySDK** ve **AdaptyUISDK** paket bağımlılıklarını projenizden kaldırın. 2. **AdaptySDK** ve **AdaptyUISDK** klasörlerini silin. 3. AdaptySDK paketini [Unity için Adapty SDK kurulumu ve yapılandırması](sdk-installation-unity) sayfasında açıklandığı gibi yeniden içe aktarın. ## Yeniden Adlandırmalar \{#renamings\} 1. Adapty modülünde yeniden adlandır: | Eski sürüm | Yeni sürüm | | ------------------------- | ------------------------ | | Adapty.sdkVersion | Adapty.SDKVersion | | Adapty.LogLevel | AdaptyLogLevel | | Adapty.Paywall | AdaptyPaywall | | Adapty.PaywallFetchPolicy | AdaptyPaywallFetchPolicy | | PaywallProduct | AdaptyPaywallProduct | | Adapty.Profile | AdaptyProfile | | Adapty.ProfileParameters | AdaptyProfileParameters | | ProfileGender | AdaptyProfileGender | | Error | AdaptyError | 2. AdaptyUI modülünde yeniden adlandırmalar: | Eski versiyon | Yeni versiyon | | ------------------ | ------------------ | | CreatePaywallView | CreateView | | PresentPaywallView | PresentView | | DismissPaywallView | DismissView | | AdaptyUI.View | AdaptyUIView | | AdaptyUI.Action | AdaptyUIUserAction | ## SetLogLevel Metodunu Güncelleme \{#change-the-setloglevel-method\} Artık `SetLogLevel` metodu bir callback kabul etmektedir. ```diff showLineNumbers - Adapty.SetLogLevel(Adapty.LogLevel.Verbose); + Adapty.SetLogLevel(Adapty.LogLevel.Verbose, null); // or you can pass the callback to handle the possible error ``` ## PresentCodeRedemptionSheet Metodunu Güncelleme \{#change-the-presentcoderedemptionsheet-method\} Artık `PresentCodeRedemptionSheet` metodu bir callback kabul etmektedir. ```diff showLineNumbers - Adapty.PresentCodeRedemptionSheet(); + Adapty.PresentCodeRedemptionSheet(null); // or you can pass the callback to handle the possible error ``` ## Paywall Görünümünün Oluşturulma Şeklini Değiştirme \{#change-how-the-paywall-view-is-created\} Tam kod örneği için [Paywall Builder ile tasarlanan paywall'ın görünüm yapılandırmasını getirme](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) bölümüne bakın. ```diff showLineNumbers + var parameters = new AdaptyUICreateViewParameters() + .SetPreloadProducts(true); - AdaptyUI.CreatePaywallView( + AdaptyUI.CreateView( paywall, - preloadProducts: true, + parameters, (view, error) => { // use the view }); ``` ## GetProductsIntroductoryOfferEligibility Metodunu Kaldırma \{#remove-the-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 öncesinde, ürün nesnesi kullanıcının uygun olup olmadığından bağımsız olarak her zaman teklifleri içeriyordu. Teklifi kullanmadan önce uygunluğu manuel olarak kontrol etmeniz gerekiyordu. Artık ürün nesnesi yalnızca kullanıcı uygunsa teklif içermektedir. Bu sayede uygunluğu ayrıca kontrol etmenize gerek kalmaz; bir teklif mevcutsa kullanıcı zaten uygundur. ## Yedek paywall sağlama yöntemi güncellendi \{#update-method-for-providing-fallback-paywalls\} Bu sürüme kadar yedek paywall'lar serileştirilmiş JSON olarak iletiliyordu. v 3.3.0 itibarıyla mekanizma değişti: 1. Yedek paywall'ları `/Assets/StreamingAssets/` dizinindeki dosyalara kaydedin; Android için bir dosya, iOS için ayrı bir dosya. 2. Dosya adlarını `SetFallbackPaywalls` metoduna geçirin. Kodunuz şu şekilde değişecek: ```diff showLineNumbers using AdaptySDK; void SetFallBackPaywalls() { + #if UNITY_IOS + var assetId = "adapty_fallback_ios.json"; + #elif UNITY_ANDROID + var assetId = "adapty_fallback_android.json"; + #else + var assetId = ""; + #endif - Adapty.SetFallbackPaywalls("FALLBACK_PAYWALLS_JSON_STRING", (error) => { + Adapty.SetFallbackPaywalls(assetId, (error) => { // handle the error }); } ``` Son kod örneğini [Unity'de yedek paywall kullanımı](unity-use-fallback-paywalls) sayfasında inceleyebilirsiniz. ## Satın alma güncelleme \{#update-making-purchase\} Daha önce iptal edilen ve beklemedeki satın almalar hata olarak değerlendirilir ve sırasıyla `PaymentCancelled` ve `PendingPurchase` kodlarını döndürürdü. Artık iptal edilen, başarılı ve beklemedeki satın almaları işlemek için yeni bir `AdaptyPurchaseResultType` sınıfı kullanılıyor. Satın alma kodunu aşağıdaki şekilde güncelleyin: ```diff showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { - Adapty.MakePurchase(product, (profile, error) => { - // handle successfull purchase + Adapty.MakePurchase(product, (result, error) => { + switch (result.Type) { + case AdaptyPurchaseResultType.Pending: + // handle pending purchase + break; + case AdaptyPurchaseResultType.UserCancelled: + // handle purchase cancellation + break; + case AdaptyPurchaseResultType.Success: + var profile = result.Profile; + // handle successful purchase + break; + default: + break; } }); } ``` Lütfen çevirmek istediğiniz MDX belgesini paylaşın. ## Paywall Builder olaylarının işlenmesini güncelleme \{#update-handling-of-paywall-builder-events\} İptal edilen ve bekleyen satın almalar artık hata olarak değerlendirilmiyor; tüm bu durumlar `PaywallViewDidFinishPurchase` metodu ile işleniyor. 1. İptal edilen satın alma olayının işlenmesini silin. 2. Başarılı satın alma olayının işlenmesini aşağıdaki şekilde güncelleyin: ```diff showLineNumbers - public void OnFinishPurchase( - AdaptyUI.View view, - Adapty.PaywallProduct product, - Adapty.Profile profile - ) { } + public void PaywallViewDidFinishPurchase( + AdaptyUIView view, + AdaptyPaywallProduct product, + AdaptyPurchaseResult purchasedResult + ) { } ``` 3. Aksiyon işlemeyi güncelleyin: ```diff showLineNumbers - public void OnPerformAction( - AdaptyUI.View view, - AdaptyUI.Action action - ) { + public void PaywallViewDidPerformAction( + AdaptyUIView view, + AdaptyUIUserAction action + ) { switch (action.Type) { - case AdaptyUI.ActionType.Close: + case AdaptyUIUserActionType.Close: view.Dismiss(null); break; - case AdaptyUI.ActionType.OpenUrl: + case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if (urlString != null { Application.OpenURL(urlString); } default: // handle other events break; } } ``` 4. Başlatılan satın alma işleminin yönetimini güncelleyin: ```diff showLineNumbers - public void OnSelectProduct( - AdaptyUI.View view, - Adapty.PaywallProduct product - ) { } + public void PaywallViewDidSelectProduct( + AdaptyUIView view, + string productId + ) { } ``` 5. Başarısız satın alma işleminin yönetimini güncelleyin: ```diff showLineNumbers - public void OnFailPurchase( - AdaptyUI.View view, - Adapty.PaywallProduct product, - Adapty.Error error - ) { } + public void PaywallViewDidFailPurchase( + AdaptyUIView view, + AdaptyPaywallProduct product, + AdaptyError error + ) { } ``` 6. Başarılı geri yükleme olayının işlenmesini güncelleyin: Check out the final code example in the [Handle paywall events](unity-handling-events) page. ## Paywall Builder paywall hatalarının işlenmesini güncelleyin \{#update-handling-of-paywall-builder-paywall-errors\} Hata işleme yöntemi de değiştirildi; lütfen aşağıdaki rehbere göre kodunuzu güncelleyin. 1. Ürün yükleme hatalarının işlenmesini güncelleyin: ```diff showLineNumbers - public void OnFailLoadingProducts( - AdaptyUI.View view, - Adapty.Error error - ) { } + public void PaywallViewDidFailLoadingProducts( + AdaptyUIView view, + AdaptyError error + ) { } ``` 2. Render hatalarının işlenmesini güncelleyin: ```diff showLineNumbers - public void OnFailRendering( - AdaptyUI.View view, - Adapty.Error error - ) { } + public void PaywallViewDidFailRendering( + AdaptyUIView view, + AdaptyError error + ) { } ``` ## Üçüncü Taraf Entegrasyon SDK Yapılandırmasını Güncelleme \{#update-third-party-integration-sdk-configuration\} Adapty Unity SDK 3.3.0'dan itibaren `updateAttribution` metodunun genel API'si güncellendi. Daha önce `[AnyHashable: Any]` sözlüğü kabul ediyordu ve attribution nesnelerini çeşitli servislerden doğrudan geçirmenize olanak tanıyordu. Artık `[String: any Sendable]` gerektirmektedir, bu nedenle attribution nesnelerini geçirmeden önce dönüştürmeniz gerekecektir. Aşağıdaki entegrasyonların Adapty Unity SDK 3.3.0 ve sonrasıyla düzgün çalışmasını sağlamak için SDK yapılandırmalarınızı aşağıdaki bölümlerde açıklandığı şekilde güncelleyin. ### Adjust Mobil uygulama kodunuzu aşağıdaki gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın. ```diff showLineNumbers - using static AdaptySDK.Adapty; using AdaptySDK; Adjust.GetAdid((adid) => { - Adjust.GetAttribution((attribution) => { - Dictionary<String, object> data = new Dictionary<String, object>(); - - data["network"] = attribution.Network; - data["campaign"] = attribution.Campaign; - data["adgroup"] = attribution.Adgroup; - data["creative"] = attribution.Creative; - - String attributionString = JsonUtility.ToJson(data); - Adapty.UpdateAttribution(attributionString, AttributionSource.Adjust, adid, (error) => { - // handle the error - }); + if (adid != null) { + Adapty.SetIntegrationIdentifier( + "adjust_device_id", + adid, + (error) => { + // handle the error + }); } }); Adjust.GetAttribution((attribution) => { Dictionary<String, object> data = new Dictionary<String, object>(); data["network"] = attribution.Network; data["campaign"] = attribution.Campaign; data["adgroup"] = attribution.Adgroup; data["creative"] = attribution.Creative; String attributionString = JsonUtility.ToJson(data); - Adapty.UpdateAttribution(attributionString, AttributionSource.Adjust, adid, (error) => { + Adapty.UpdateAttribution(attributionString, "adjust", (error) => { // handle the error }); }); ``` ### Amplitude Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) sayfasına bakın. ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetAmplitudeUserId("YOUR_AMPLITUDE_USER_ID"); - builder.SetAmplitudeDeviceId(amplitude.getDeviceId()); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + Adapty.SetIntegrationIdentifier( + "amplitude_user_id", + "YOUR_AMPLITUDE_USER_ID", + (error) => { + // handle the error + }); + Adapty.SetIntegrationIdentifier( + "amplitude_device_id", + amplitude.getDeviceId(), + (error) => { + // handle the error + }); ``` ### AppMetrica Aşağıda gösterildiği gibi mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [AppMetrica entegrasyonu için SDK yapılandırması](appmetrica#sdk-configuration) sayfasına bakın. ```diff showLineNumbers using AdaptySDK; - var deviceId = AppMetrica.GetDeviceId(); - if (deviceId != null { - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - builder.SetAppmetricaDeviceId(deviceId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); - } + var deviceId = AppMetrica.GetDeviceId(); + if (deviceId != null { + Adapty.SetIntegrationIdentifier( + "appmetrica_device_id", + deviceId, + (error) => { + // handle the error + }); + + Adapty.SetIntegrationIdentifier( + "appmetrica_profile_id", + "YOUR_ADAPTY_CUSTOMER_USER_ID", + (error) => { + // handle the error + }); + } ``` ### AppsFlyer Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonunda SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) bölümüne bakın. ```diff showLineNumbers using AppsFlyerSDK; using AdaptySDK; // before SDK initialization AppsFlyer.getConversionData(this.name); // in your IAppsFlyerConversionData void onConversionDataSuccess(string conversionData) { // It's important to include the network user ID - string appsFlyerId = AppsFlyer.getAppsFlyerId(); - Adapty.UpdateAttribution(conversionData, AttributionSource.Appsflyer, appsFlyerId, (error) => { + string appsFlyerId = AppsFlyer.getAppsFlyerId(); + + Adapty.SetIntegrationIdentifier( + "appsflyer_id", + appsFlyerId, + (error) => { // handle the error }); + + Adapty.UpdateAttribution( + conversionData, + "appsflyer", + (error) => { + // handle the error + }); } ``` ### Branch Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırmasına](branch#connect-your-app-to-branch) göz atın. ```diff showLineNumbers using AdaptySDK; - class YourBranchImplementation { - func initializeBranch() { - Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in - if let data { - Adapty.updateAttribution(data, source: .branch) - } - } - } - } + Branch.initSession(delegate(Dictionary<string, object> parameters, string error) { + string attributionString = JsonUtility.ToJson(parameters); + + Adapty.UpdateAttribution( + attributionString, + "branch", + (error) => { + // handle the error + }); + }); ``` ### Firebase ve Google Analytics \{#firebase-and-google-analytics\} Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın. ```diff showLineNumbers // We suppose FirebaseAnalytics Unity Plugin is already installed using AdaptySDK; Firebase.Analytics .FirebaseAnalytics .GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread((task) => { if (!task.IsCompletedSuccessfully) { // handle error return; } var firebaseId = task.Result var builder = new Adapty.ProfileParameters.Builder(); - builder.SetFirebaseAppInstanceId(firebaseId); - - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error + Adapty.SetIntegrationIdentifier( + "firebase_app_instance_id", + firebaseId, + (error) => { + // handle the error }); }); ``` ### Mixpanel Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonu için SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın. ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetMixpanelUserId(Mixpanel.DistinctId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + var distinctId = Mixpanel.DistinctId; + if (distinctId != null) { + Adapty.SetIntegrationIdentifier( + "mixpanel_user_id", + distinctId, + (error) => { + // handle the error + }); + } ``` ### OneSignal Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) sayfasına bakın. ```diff showLineNumbers using AdaptySDK; - using OneSignalSDK; - var pushUserId = OneSignal.Default.PushSubscriptionState.userId; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetOneSignalPlayerId(pushUserId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + var distinctId = Mixpanel.DistinctId; + if (distinctId != null) { + Adapty.SetIntegrationIdentifier( + "mixpanel_user_id", + distinctId, + (error) => { + // handle the error + }); + } ``` ### Pushwoosh Mobil uygulama kodunuzu aşağıdaki şekilde güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonu için SDK yapılandırması](pushwoosh#sdk-configuration) sayfasına bakın. ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetPushwooshHWID(Pushwoosh.Instance.HWID); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + Adapty.SetIntegrationIdentifier( + "pushwoosh_hwid", + Pushwoosh.Instance.HWID, + (error) => { + // handle the error + }); ``` ## Observer mode uygulamasını güncelleyin \{#update-observer-mode-implementation\} Paywall'ları işlemlere bağlama şeklinizi güncelleyin. Daha önce `variationId` atamak için `setVariationId` metodunu kullanıyordunuz. Artık yeni `reportTransaction` metoduyla işlemi kaydederken `variationId`'yi doğrudan dahil edebilirsiniz. Son kod örneğine [Observer modunda paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode-unity) sayfasından bakabilirsiniz. ```diff showLineNumbers // every time when calling transaction.finish() - Adapty.SetVariationForTransaction("<variationId>", "<transactionId>", (error) => { - if(error != null) { - // handle the error - return; - } - - // successful binding - }); + Adapty.ReportTransaction( + "YOUR_TRANSACTION_ID", + "PAYWALL_VARIATION_ID", // optional + (error) => { + // handle the error + }); ``` ## Unity Eklenti Başlatmasını Güncelleme \{#update-the-unity-plugin-initialization\} Adapty Unity SDK 3.3.0'dan itibaren, eklenti başlatılırken `Activate` metodunun açıkça çağrılması zorunludur: ```csharp showLineNumbers Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` --- # File: migration-to-unity-sdk-v3 --- --- title: "Adapty Unity SDK'yı v3.0'a Taşıma" description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty Unity SDK v3.0'a geçiş yapın." --- Adapty SDK v3.0, yeni ve heyecan verici [Adapty Paywall Builder](adapty-paywall-builder)'ı desteklemektedir. Bu, paywall oluşturmak için kullanılan, kod gerektirmeyen ve kullanıcı dostu aracın yeni sürümüdür. Maksimum esnekliği ve zengin tasarım özellikleriyle paywalllarınız çok daha etkili ve kârlı hale gelecektir. ## Yükseltme süreci \{#upgrade-process\} Unity için yükseltme süreci diğer platformlarla aynı adımları içerir: 1. Adapty SDK v3.x sürümüne yükseltin 2. Mevcut paywall'larınızı yeni Paywall Builder'a taşıyın Unity'ye özgü ayrıntılı geçiş talimatları için lütfen [Unity SDK kurulum kılavuzuna](sdk-installation-unity) bakın ve ana geçiş kılavuzunda belirtilen genel geçiş adımlarını izleyin. --- # File: unity-migration-guide --- --- title: "SDK migrasyon rehberi" description: "Unity Adapty SDK için migrasyon rehberleri." --- ## Migrasyon Rehberleri \{#migration-guides\} ### [Unity Adapty SDK 3.x'e migrasyon rehberi](unity-sdk-migration-guides) Eski sürümlerden Unity Adapty SDK 3.x'e nasıl geçileceğini öğrenin. ## Yenilikler \{#whats-new\} ### Sürüm 3.x \{#version-3x\} - Geliştirilmiş paywall sunumu - İyileştirilmiş hata yönetimi - Daha iyi C# desteği - Performans optimizasyonları ### Sürüm 2.x \{#version-2x\} - Yeni onboarding özellikleri - Geliştirilmiş analitik - İyileştirilmiş satın alma akışı - Hata düzeltmeleri ve kararlılık iyileştirmeleri ## Kırıcı Değişiklikler \{#breaking-changes\} ### Sürüm 3.x \{#version-3x-breaking\} - Güncellenmiş observer API'ı - Değiştirilen paywall sunum metodları - Düzenlenmiş hata yönetimi yapısı ### Sürüm 2.x \{#version-2x-breaking\} - Güncellenmiş onboarding API'ı - Değiştirilen profil yapısı - Düzenlenmiş satın alma akışı ## Migrasyon Kontrol Listesi \{#migration-checklist\} Yeni bir sürüme geçerken: - [ ] Kırıcı değişiklikleri inceleyin - [ ] API çağrılarını güncelleyin - [ ] Tüm işlevselliği test edin - [ ] Hata yönetimini güncelleyin - [ ] Analitik takibini doğrulayın - [ ] Tüm platformlarda test edin --- # End of Documentation _Generated on: 2026-07-24T13:02:34.608Z_ _Successfully processed: 41/41 files_