# CAPACITOR - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: fr Generated on: 2026-08-04T15:08:25.938Z Total files: 45 --- # File: capacitor-sdk-overview --- --- title: "Présentation du SDK Capacitor" description: "Découvrez le SDK Adapty pour Capacitor et ses principales fonctionnalités." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Bienvenue ! Nous sommes là pour simplifier vos achats intégrés 🚀 Nous avons conçu le [SDK Adapty pour Capacitor](https://github.com/adaptyteam/AdaptySDK-Capacitor/) pour vous libérer des contraintes liées aux achats intégrés, afin que vous puissiez vous concentrer sur ce que vous faites le mieux — créer des applications exceptionnelles. Voici ce que nous gérons pour vous : - Gestion des achats, validation des reçus et gestion des abonnements clés en main - Création et test de paywalls sans mise à jour de l'application - Analyses d'achats détaillées sans configuration — cohortes, LTV, taux de désabonnement et analyse de l'entonnoir inclus - Maintien du statut d'abonnement de l'utilisateur toujours à jour entre les sessions et les appareils - Intégration de votre application avec des services d'attribution marketing et d'analyse en une seule ligne de code :::note Avant de plonger dans le code, vous devrez intégrer Adapty avec App Store Connect et Google Play Console, puis configurer des produits dans le tableau de bord. Consultez notre [guide de démarrage rapide](quickstart) pour tout configurer en premier. ::: ## Démarrer \{#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. Voici ce que nous allons aborder dans le guide d'intégration : 1. [Installer et configurer le SDK](sdk-installation-capacitor) : Ajoutez le SDK comme [dépendance](https://www.npmjs.com/package/@adapty/capacitor) à votre projet et activez-le dans le code. 2. [Activer les achats via les paywalls](capacitor-quickstart-paywalls) : Configurez le flux d'achat pour que les utilisateurs puissent acheter des produits. 3. [Vérifier le statut de l'abonnement](capacitor-check-subscription-status) : Vérifiez automatiquement l'état d'abonnement de l'utilisateur et contrôlez son accès au contenu payant. 4. [Identifier les utilisateurs (optionnel)](capacitor-quickstart-identify) : Associez les utilisateurs à leurs profils Adapty pour garantir la cohérence de leurs données sur tous les appareils. ### Voir en action \{#see-it-in-action\} Vous voulez voir comment tout s'assemble ? Nous avons ce qu'il vous faut : **Exemples d'applications** : Consultez nos exemples complets qui illustrent la configuration complète : - [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) - [Outils de développement avancés](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools) ## Concepts principaux \{#main-concepts\} Avant de plonger dans le code, familiarisons-nous avec les concepts clés qui font fonctionner Adapty. L'approche d'Adapty repose sur le fait que seuls les placements sont codés en dur dans votre application. Tout le reste — produits, designs de paywalls, tarification et offres — peut être géré de manière flexible depuis l'Adapty Dashboard sans mise à jour de l'application : 1. **Produit** - Tout ce qui est disponible à l'achat dans votre application — abonnement, produit consommable ou accès à vie. 2. **Flow ou paywall** - Des produits regroupés avec une configuration, rattachés à un placement. Deux variantes : - **[Flow](adapty-flow-builder)** - Interface visuelle sans code, créée dans le Flow Builder. Adapty affiche l'interface utilisateur et gère l'achat pour vous. - **[Paywall](paywalls)** - Pas de configuration visuelle ; vous créez l'interface dans votre propre code et appelez `makePurchase` vous-même. Voir [Implémenter les paywalls manuellement](capacitor-quickstart-manual). Dans le code du SDK, les deux sont récupérés via la même méthode `getFlow`. 3. **Placement** - Un point stratégique dans le parcours utilisateur où vous souhaitez afficher un paywall. Considérez les placements comme le « où » et le « quand » de votre stratégie de monétisation. Les placements courants incluent : - `main` - Votre emplacement de paywall principal - `onboarding` - Affiché pendant le flow d'onboarding utilisateur - `settings` - Accessible depuis les paramètres de votre application Commencez par les bases comme `main` ou `onboarding` pour votre première intégration, puis réfléchissez aux autres endroits dans votre application où les utilisateurs pourraient être prêts à acheter. 4. **Profil** - Lorsque les utilisateurs achètent un produit, leur profil se voit attribuer un **niveau d'accès** que vous utilisez pour définir l'accès aux fonctionnalités payantes. --- # File: sdk-installation-capacitor --- --- title: "Capacitor - Installation & configuration du SDK Adapty" description: "Guide étape par étape pour installer le SDK Adapty sur Capacitor pour les applications basées sur des abonnements." --- Le SDK Adapty comprend deux modules essentiels pour une intégration fluide dans votre application Capacitor : - **Core Adapty** : Ce module est indispensable au bon fonctionnement d'Adapty dans votre application. - **AdaptyUI** : Ce module est nécessaire si vous utilisez le [Adapty Paywall Builder](adapty-paywall-builder), un outil no-code convivial pour créer facilement des paywalls multiplateformes. AdaptyUI est automatiquement activé avec le module principal. :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et autres fonctionnalités de base. ::: ## Prérequis \{#requirements\} Le [SDK Adapty Capacitor](https://github.com/adaptyteam/AdaptySDK-Capacitor/) requiert les versions suivantes : | Version du SDK Adapty | Version de Capacitor | Version iOS | |-----------------------|----------------------|-------------| | 3.16.0+ | 8 | 15.0+ | | 3.15 | 7 | 14.0+ | Les versions 6 et inférieures de Capacitor ne sont pas prises en charge. La création pour iOS avec Adapty SDK v4 (bêta) nécessite **Xcode 26** ou version ultérieure — le SDK iOS natif qu'il utilise est compilé avec Swift tools 6.2. Les exigences iOS 15.0+, Capacitor 8 et Android minSdk 24 sont identiques à celles du SDK 3.16+. :::info À partir du SDK v3.17, Adapty SDK utilise Google Play Billing Library v8.0.0 par défaut. ::: :::info L'installation du SDK correspond à l'étape 5 de la configuration d'Adapty. Avant que les achats fonctionnent dans votre app, vous devez également connecter votre app aux stores, puis créer des produits, un paywall et un placement dans l'Adapty Dashboard. Le [guide de démarrage rapide](quickstart) décrit toutes les étapes requises. ::: ## Installer le SDK Adapty \{#install-adapty-sdk\} :::important Les étapes ci-dessous installent le SDK Adapty 3.x. Le SDK v4 (bêta) — requis pour le [Flow Builder](adapty-flow-builder) et utilisé par le [démarrage rapide](capacitor-quickstart-paywalls) — s'installe différemment : suivez [SDK Adapty 4.0 (bêta)](#adapty-sdk-40-beta) ci-dessous, ou consultez le [guide de migration](migration-to-capacitor-sdk-v4). ::: [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Installez le SDK Adapty : ```sh npm install @adapty/capacitor npx cap sync ``` ### Adapty SDK 4.0 (beta) Capacitor SDK 4.0 — qui ajoute la prise en charge du [Flow Builder](adapty-flow-builder) — est une version préliminaire. Installez la version exacte (npm ne résout pas les pré-versions via les plages caret/tilde), puis synchronisez : ```sh npm install @adapty/capacitor@4.0.1-beta.1 ``` ```sh npx cap sync ``` Sur iOS, la v4 récupère les SDK natifs Adapty via **Swift Package Manager uniquement** — le podspec CocoaPods a été supprimé ([le dépôt de specs CocoaPods passe en lecture seule en décembre 2026](https://blog.cocoapods.org/CocoaPods-Specs-Repo/)). Le projet iOS de votre application doit utiliser l'intégration SPM de Capacitor : - Pour les nouvelles applications, ajoutez la plateforme iOS avec le gestionnaire de paquets SPM : ```sh npx cap add ios --packagemanager SPM ``` - Pour les applications existantes, migrez le projet iOS de CocoaPods vers SPM en suivant [le guide Capacitor pour utiliser SPM dans un projet existant](https://capacitorjs.com/docs/ios/spm#using-spm-in-an-existing-capacitor-project). Pour la liste complète des changements d'API en v4, consultez [Migrer le SDK Adapty Capacitor vers la v4](migration-to-capacitor-sdk-v4). ## Activer le module Adapty du SDK \{#activate-adapty-module-of-adapty-sdk\} :::note Le SDK n'a besoin d'être activé qu'une seule fois dans votre application. ::: Pour obtenir votre **Public SDK Key** : 1. Accédez à l'Adapty Dashboard et naviguez vers [**App settings → General**](https://app.adapty.io/settings/general). 2. Dans la section **Api keys**, copiez la **Public SDK Key** (et NON la Secret Key). 3. Remplacez `"YOUR_PUBLIC_SDK_KEY"` dans le code. Ou obtenez-la de façon programmatique via l'[Adapty CLI](developer-cli) : ``` npm install -g adapty adapty auth login adapty apps list ``` Ou, directement : ``` npx adapty auth login adapty apps list ``` - Assurez-vous d'utiliser la **Public SDK key** pour l'initialisation d'Adapty — la **Secret key** ne doit être utilisée que pour l'[API côté serveur](getting-started-with-server-side-api). - Les **SDK keys** sont propres à chaque application, donc si vous avez plusieurs applications, veillez à choisir la bonne. Copiez le code suivant dans n'importe quel fichier de l'application pour activer Adapty : ```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 Attendez que `activate` soit résolu avant d'appeler toute autre méthode du SDK Adapty. Consultez [L'ordre des appels dans le SDK Capacitor](capacitor-sdk-call-order) pour la séquence complète. ::: :::tip Pour éviter les erreurs d'activation en environnement de développement, utilisez les [conseils](#development-environment-tips). ::: Configurez maintenant les paywalls dans votre application : - Si vous utilisez [Adapty Paywall Builder](adapty-paywall-builder), suivez le [démarrage rapide avec Paywall Builder](capacitor-quickstart-paywalls). - Si vous construisez votre propre interface de paywall, consultez le [démarrage rapide pour les paywalls personnalisés](capacitor-quickstart-manual). ## Activer le module AdaptyUI du SDK Adapty \{#activate-adaptyui-module-of-adapty-sdk\} Si vous prévoyez d'utiliser le [Paywall Builder](adapty-paywall-builder), vous avez besoin du module AdaptyUI. Il est activé automatiquement lors de l'activation du module principal ; vous n'avez rien d'autre à faire. ## Configuration optionnelle \{#optional-setup\} ### Journalisation \{#logging\} #### Configurer le système de journalisation \{#set-up-the-logging-system\} Adapty enregistre les erreurs et d'autres informations importantes pour vous aider à comprendre ce qui se passe. Les niveaux disponibles sont les suivants : | Level | Description | | ---------- | ------------------------------------------------------------ | | `error` | Seules les erreurs seront enregistrées | | `warn` | Les erreurs et les messages du SDK qui ne causent pas d'erreurs critiques, mais qui méritent attention, seront enregistrés | | `info` | Les erreurs, avertissements et divers messages d'information seront enregistrés | | `verbose` | Toute information supplémentaire pouvant être utile lors du débogage, comme les appels de fonctions, les requêtes API, etc., sera enregistrée | Vous pouvez définir le niveau de log dans votre application avant ou pendant la configuration d'Adapty : ```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', } }); ``` ### Politiques de données \{#data-policies\} Adapty ne stocke pas les données personnelles de vos utilisateurs, sauf si vous les envoyez explicitement. Vous pouvez toutefois mettre en place des politiques de sécurité des données supplémentaires pour respecter les directives du store ou de votre pays. #### Désactiver la collecte et le partage des adresses IP \{#disable-ip-address-collection-and-sharing\} Lors de l'activation du module Adapty, définissez `ipAddressCollectionDisabled` à `true` pour désactiver la collecte et le partage des adresses IP des utilisateurs. La valeur par défaut est `false`. Utilisez ce paramètre pour renforcer la confidentialité des utilisateurs, vous conformer aux réglementations régionales de protection des données (comme le RGPD ou le CCPA), ou réduire la collecte de données inutile lorsque les fonctionnalités basées sur l'IP ne sont pas requises pour votre application. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ipAddressCollectionDisabled: true, } }); ``` #### Désactiver la collecte et le partage de l'identifiant publicitaire \{#disable-advertising-id-collection-and-sharing\} Lors de l'activation du module Adapty, définissez `ios.idfaCollectionDisabled` (iOS) ou `android.adIdCollectionDisabled` (Android) sur `true` pour désactiver la collecte des identifiants publicitaires. La valeur par défaut est `false`. Utilisez ce paramètre pour respecter les politiques de l'App Store/Play Store, éviter de déclencher la demande App Tracking Transparency, ou si votre application n'a pas besoin d'attribution publicitaire ni d'analytics basée sur des identifiants publicitaires. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, } }); ``` #### Configurer le cache média pour AdaptyUI \{#set-up-media-cache-configuration-for-adaptyui\} Par défaut, AdaptyUI met en cache les médias (images et vidéos) pour améliorer les performances et réduire l'utilisation du réseau. Vous pouvez personnaliser ces paramètres en fournissant une configuration personnalisée. Utilisez `mediaCache` pour remplacer les paramètres de cache par défaut : ```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 }, } }); ``` | Paramètre | Requis | Description | |-----------|--------|-------------| | memoryStorageTotalCostLimit | optionnel | Taille totale du cache en mémoire, en octets. Valeur par défaut spécifique à la plateforme. | | memoryStorageCountLimit | optionnel | Limite du nombre d'éléments dans le stockage en mémoire. Valeur par défaut spécifique à la plateforme. | | diskStorageSizeLimit | optionnel | Limite de taille des fichiers sur le disque, en octets. Valeur par défaut spécifique à la plateforme. | ### Activer les niveaux d'accès locaux (Android) \{#enable-local-access-levels-android\} Par défaut, les [niveaux d'accès locaux](local-access-levels) sont activés sur iOS et désactivés sur Android. Pour les activer également sur Android, définissez `localAccessLevelAllowed` sur `true` : ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { localAccessLevelAllowed: true, }, } }); ``` ### Effacer les données lors d'une restauration depuis une sauvegarde \{#clear-data-on-backup-restore\} Lorsque `clearDataOnBackup` est défini sur `true`, le SDK détecte quand l'application est restaurée depuis une sauvegarde iCloud et supprime toutes les données SDK stockées localement, notamment les informations de profil mises en cache, les détails des produits et les paywalls. Le SDK s'initialise ensuite dans un état vierge. La valeur par défaut est `false`. :::note Seul le cache local du SDK est supprimé. L'historique des transactions avec Apple et les données utilisateur sur les serveurs Adapty restent inchangés. ::: ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { clearDataOnBackup: true, }, } }); ``` ## Conseils pour l'environnement de développement \{#development-environment-tips\} #### Résoudre les erreurs d'activation du SDK avec le rechargement en direct de Capacitor \{#troubleshoot-sdk-activation-errors-on-capacitors-live-reload\} Lors du développement avec le SDK Adapty dans Capacitor, vous pouvez rencontrer l'erreur : `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` Ce problème survient car la fonctionnalité de rechargement en direct de Capacitor déclenche plusieurs appels d'activation pendant le développement. Pour l'éviter, utilisez l'option `__ignoreActivationOnFastRefresh` définie sur l'indicateur de mode développement de Capacitor – il diffère selon le bundle que vous utilisez. ```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 } ``` ## Dépannage \{#troubleshooting\} #### Erreur de version iOS minimale \{#minimum-ios-version-error\} :::note Ceci s'applique aux projets basés sur CocoaPods avec le **SDK 3.x**. Le SDK 4.0 s'installe sur iOS via Swift Package Manager uniquement (il n'y a pas de `Podfile`) et nécessite iOS 15.0 — définissez votre cible de déploiement sur 15.0 dans Xcode. ::: Si vous obtenez une erreur de version iOS minimale avec le SDK 3.x, mettez à jour votre Podfile : ```diff -platform :ios, min_ios_version_supported +platform :ios, '15.0' ``` #### Règles de sauvegarde Android (configuration Auto Backup) \{#android-backup-rules-auto-backup-configuration\} Certains SDKs (dont Adapty) embarquent leur propre configuration Android Auto Backup. Si vous utilisez plusieurs SDKs qui définissent des règles de sauvegarde, la fusion du manifeste Android peut échouer avec une erreur mentionnant `android:fullBackupContent`, `android:dataExtractionRules` ou `android:allowBackup`. Symptômes typiques : `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 Ces modifications doivent être effectuées dans votre répertoire de la plateforme Android (généralement situé dans le dossier `android/` de votre projet). ::: Pour résoudre ce problème, vous devez : - Indiquer au gestionnaire de fusion de manifeste d'utiliser les valeurs de votre application pour les attributs liés à la sauvegarde. - Créer des fichiers de règles de sauvegarde qui fusionnent les règles d'Adapty avec celles des autres SDKs. #### 1. Ajoutez l'espace de noms `tools` à votre manifeste \{#1-add-the-tools-namespace-to-your-manifest\} Dans votre fichier `AndroidManifest.xml`, assurez-vous que la balise racine `` inclut tools : ```xml ... ``` #### 2. Remplacez les attributs de sauvegarde dans `` \{#2-override-backup-attributes-in-application\} Dans le même fichier `AndroidManifest.xml`, mettez à jour la balise `` afin que votre application fournisse les valeurs finales et indique au gestionnaire de fusion de remplacer les valeurs des bibliothèques : ```xml ... ``` Si un SDK définit également `android:allowBackup`, incluez-le dans `tools:replace` : ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. Créez les fichiers de règles de sauvegarde fusionnés \{#3-create-merged-backup-rules-files\} Créez des fichiers XML dans le répertoire `res/xml/` de votre projet Android, en combinant les règles d'Adapty avec celles des autres SDKs. Android utilise des formats de règles de sauvegarde différents selon la version de l'OS, donc créer les deux fichiers garantit la compatibilité avec toutes les versions d'Android prises en charge par votre application. :::note Les exemples ci-dessous utilisent AppsFlyer comme exemple de SDK tiers. Remplacez ou ajoutez des règles pour tout autre SDK que vous utilisez dans votre application. ::: **Pour Android 12 et supérieur** (utilise le nouveau format de règles d'extraction de données) : ```xml title="sample_data_extraction_rules.xml" ``` **Pour Android 11 et inférieur** (utilise l'ancien format de sauvegarde complète) : ```xml title="sample_backup_rules.xml" :::tip Après avoir modifié des fichiers Android natifs, exécutez `npx cap sync android` pour que Capacitor prenne en compte les ressources mises à jour si vous regénérez la plateforme. ::: #### Les achats échouent au retour d'une autre application sur Android \{#purchases-fail-after-returning-from-another-app-in-android\} Si l'Activity qui démarre le flow d'achat utilise un `launchMode` non standard, Android peut la recréer ou la réutiliser incorrectement lorsque l'utilisateur revient de Google Play, d'une application bancaire ou d'un navigateur. Cela peut entraîner la perte du résultat de l'achat ou son interprétation comme une annulation. Pour vous assurer que les achats fonctionnent correctement, utilisez uniquement les modes de lancement `standard` ou `singleTop` pour l'Activity qui démarre le flux d'achat, et évitez tout autre mode. Dans votre `AndroidManifest.xml`, assurez-vous que l'Activity qui démarre le flux d'achat est configurée sur `standard` ou `singleTop` : ```xml ``` #### Erreurs de build Swift 6 causées par la substitution de SWIFT_VERSION dans le Podfile :::note Cela s'applique aux projets basés sur CocoaPods avec le **SDK 3.x**. Le SDK 4.0 installe les SDK natifs via Swift Package Manager, il n'y a donc pas de `Podfile` à modifier. ::: Lors de la compilation de votre application Capacitor pour iOS, vous pouvez rencontrer des erreurs de compilation Swift 6 sur les targets de pods Adapty. Les symptômes typiques incluent des incompatibilités `@Sendable` dans `AdaptyUIBuilderLogic`, une conformité `Sendable` manquante sur les types Adapty, ou des erreurs d'isolation d'acteur. Les pods Adapty déclarent `s.swift_version = '6.0'` et nécessitent Swift 6 pour compiler. Votre propre code d'application peut rester en Swift 5 — seuls les targets des pods Adapty (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`, `AdaptyLogger`, `AdaptyPlugin`) ont besoin d'être compilés avec Swift 6. La cause la plus fréquente est un hook `post_install` dans `ios/App/Podfile` qui réécrit `SWIFT_VERSION` pour chaque target de pod : ```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 ``` **Correctif** : Excluez les cibles de pod Adapty de la surcharge : ```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 ``` Ensuite, exécutez `npx cap sync ios` et recompilez. Pour vérifier, ouvrez `ios/App/Pods/Pods.xcodeproj`, sélectionnez la cible du pod `Adapty` → **Build Settings** → **Swift Language Version**. La valeur devrait être **Swift 6**. --- # File: capacitor-quickstart-paywalls --- --- title: "Activer les achats avec Flow Builder dans le SDK Capacitor" description: "Guide de démarrage rapide pour activer les achats intégrés avec Adapty Flow Builder." --- Pour activer les achats intégrés, vous devez comprendre trois concepts clés : - [**Produits**](product) – tout ce que les utilisateurs peuvent acheter (abonnements, consommables, accès à vie) - [**Flows**](adapty-flow-builder) – séquences d'écrans qui présentent des produits aux utilisateurs, construites dans le Flow Builder sans code. Le SDK les récupère via `getFlow`. Si vous préférez construire l'interface dans votre propre code, utilisez un paywall à la place — voir [Implémenter des paywalls manuellement](capacitor-quickstart-manual). - [**Placements**](placements) – où et quand vous affichez des flows dans votre application (comme `main`, `onboarding`, `settings`). Vous associez des flows à des placements dans le tableau de bord, puis vous les demandez par ID de placement dans votre code. Cela facilite l'exécution de tests A/B et l'affichage de flows différents selon les utilisateurs. Adapty vous propose trois façons d'activer les achats dans votre application. Choisissez celle qui correspond le mieux à vos besoins : | Implémentation | Complexité | Quand l'utiliser | |---|---|---| | Adapty Flow Builder | ✅ Facile | Vous [créez un flow complet et prêt à l'achat dans le builder sans code](quickstart-paywalls). Adapty l'affiche automatiquement et gère tout le processus d'achat, la validation des reçus et la gestion des abonnements en coulisses. | | Paywalls créés manuellement | 🟡 Moyen | Vous implémentez votre interface de paywall dans le code de votre application, mais récupérez quand même l'objet flow depuis Adapty pour garder de la flexibilité sur les offres de produits. Voir le [guide](capacitor-quickstart-manual). | | Mode observateur | 🔴 Difficile | Vous disposez déjà de votre propre infrastructure de gestion des achats et souhaitez continuer à l'utiliser. Notez que le mode observateur a ses limitations dans Adapty. Voir l'[article](observer-vs-full-mode). | :::important **Les étapes ci-dessous montrent comment implémenter un flow créé dans Adapty Flow Builder.** Si vous préférez construire vous-même l'interface du paywall, voir [Implémenter des paywalls manuellement](capacitor-quickstart-manual). ::: Pour afficher un flow créé dans Adapty Flow Builder, vous n'avez besoin que de : 1. **Récupérer le flow** : Obtenez-le depuis Adapty. 2. **L'afficher et Adapty gérera les achats à votre place** : Affichez la vue dans votre application. 3. **Gérer les actions des boutons** : Associez les interactions utilisateur aux réponses de votre application. Par exemple, ouvrir des liens ou fermer le flow lorsque les utilisateurs cliquent sur des boutons. ## Avant de commencer \{#before-you-start\} Avant de commencer, effectuez ces étapes : 1. Connectez votre application à l'[App Store](initial_ios) et/ou à [Google Play](initial-android) dans l'Adapty Dashboard. 2. [Créez vos produits](create-product) dans Adapty. 3. [Créez un flow et ajoutez-y des produits](create-paywall). 4. [Créez un placement et ajoutez-y votre flow](create-placement). 5. [Installez et activez le SDK Adapty](sdk-installation-capacitor) dans le code de votre application. Ce guide utilise les API Adapty Capacitor SDK v4. ## 1. Récupérer le flow \{#1-get-the-flow\} Vos flows sont associés à des placements configurés dans le tableau de bord. Les placements vous permettent d'exécuter différents flows pour différentes audiences ou de lancer des [tests A/B](ab-tests). Pour obtenir un flow créé dans Adapty Flow Builder, récupérez l'objet `flow` par l'ID de [placement](placements) à l'aide de la méthode `getFlow`. Le flow contient les éléments d'interface et le style nécessaires à son affichage. ```typescript showLineNumbers title="Capacitor" try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested flow } catch (error) { // handle the error } ``` ## 2. Afficher le flow \{#2-display-the-flow\} Maintenant que vous avez le flow, quelques lignes suffisent pour l'afficher. Créez une `view` avec la méthode `createFlowView`, définissez ses gestionnaires d'événements, puis appelez `view.present()`. Chaque `view` ne peut être utilisée qu'une seule fois. Si vous devez afficher le flow à nouveau, appelez `createFlowView` une nouvelle fois pour créer une nouvelle instance de `view`. ```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 Pour plus de détails sur l'affichage d'un flow, consultez notre [guide](capacitor-present-paywalls). ::: ## 3. Gérer les actions des boutons \{#3-handle-button-actions\} Lorsque les utilisateurs cliquent sur des boutons dans le flow, le SDK Capacitor gère automatiquement les achats, la restauration, la fermeture du flow et l'ouverture des URL. Cependant, d'autres boutons ont des ID personnalisés ou prédéfinis et nécessitent de gérer les actions dans votre code. Vous pouvez également vouloir remplacer leur comportement par défaut. Par exemple, voici le comportement par défaut du bouton de fermeture. Vous n'avez pas besoin de l'ajouter dans le code, mais vous pouvez voir ici comment procéder si nécessaire. ```typescript showLineNumbers title="Capacitor" const unsubscribe = await view.setEventHandlers({ onCloseButtonPress() { return true; // allow the flow to close }, }); ``` :::tip Consultez nos guides sur la gestion des [actions](capacitor-handle-paywall-actions) et des [événements](capacitor-handling-events) des boutons. ::: ## Étapes suivantes \{#next-steps\} :::tip Des questions ou des problèmes ? Consultez notre [forum d'assistance](https://adapty.featurebase.app/) où vous trouverez des réponses aux questions fréquentes ou pourrez poser les vôtres. Notre équipe et notre communauté sont là pour vous aider ! ::: Votre flow est prêt à être affiché dans l'application. [Testez vos achats](capacitor-test) pour vous assurer de pouvoir effectuer un achat test depuis le flow. Vous devez ensuite [vérifier le niveau d'accès des utilisateurs](capacitor-check-subscription-status) pour vous assurer d'afficher un flow ou de donner accès aux fonctionnalités payantes aux bons utilisateurs. ## Exemple complet \{#full-example\} Voici comment intégrer ensemble toutes les étapes de ce guide dans votre application. ```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: "Vérifier le statut d'abonnement dans le SDK Capacitor" description: "Apprenez à vérifier le statut d'abonnement dans votre app Capacitor avec Adapty." --- Pour décider si les utilisateurs peuvent accéder au contenu payant ou voir un paywall, vous devez vérifier leur [niveau d'accès](access-level) dans le profil. Cet article vous montre comment accéder à l'état du profil afin de déterminer ce que l'utilisateur doit voir — lui afficher un paywall ou lui donner accès aux fonctionnalités payantes. ## Obtenir le statut d'abonnement \{#get-subscription-status\} Lorsque vous décidez d'afficher un paywall ou du contenu payant à un utilisateur, vous vérifiez son [niveau d'accès](access-level) dans son profil. Deux options s'offrent à vous : - Appelez `getProfile` si vous avez besoin des dernières données du profil immédiatement (par exemple au démarrage de l'app) ou si vous souhaitez forcer une mise à jour. - Configurez des **mises à jour automatiques du profil** pour conserver une copie locale qui se rafraîchit automatiquement dès que le statut d'abonnement change. ### Récupérer le profil \{#get-profile\} La façon la plus simple d'obtenir le statut d'abonnement est d'utiliser la méthode `getProfile` pour accéder au profil : ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` ### Écouter les mises à jour d'abonnement \{#listen-to-subscription-updates\} Pour recevoir automatiquement les mises à jour du profil dans votre app : 1. Utilisez `adapty.addListener('onLatestProfileLoad')` pour écouter les changements de profil — Adapty appellera automatiquement cette méthode chaque fois que le statut d'abonnement de l'utilisateur change. 2. Stockez les données du profil mis à jour lorsque cette méthode est appelée, afin de pouvoir les utiliser partout dans votre app sans effectuer de requêtes réseau supplémentaires. ```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 appelle automatiquement le listener d'événement `onLatestProfileLoad` au démarrage de votre app, fournissant les données d'abonnement en cache même si l'appareil est hors ligne. ::: ## Connecter le profil avec la logique de paywall \{#connect-profile-with-paywall-logic\} Lorsque vous devez prendre des décisions immédiates concernant l'affichage de paywalls ou l'accès aux fonctionnalités payantes, vous pouvez vérifier le profil de l'utilisateur directement. Cette approche est utile dans des scénarios comme le démarrage de l'app, l'accès aux sections premium ou l'affichage de contenus spécifiques. ```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); } }; ``` ## Étapes suivantes \{#next-steps\} Maintenant que vous savez comment suivre le statut d'abonnement, apprenez à [travailler avec les profils utilisateurs](capacitor-quickstart-identify) pour vous assurer qu'ils ont accès à ce pour quoi ils ont payé. --- # File: capacitor-quickstart-identify --- --- title: "Identifier les utilisateurs dans le SDK Capacitor" description: "Guide de démarrage rapide pour configurer Adapty pour la gestion des abonnements intégrés dans Capacitor." --- La façon dont vous gérez les achats des utilisateurs dépend du modèle d'authentification de votre application : - Si votre application n'utilise pas d'authentification backend et ne stocke pas de données utilisateur, consultez la [section sur les utilisateurs anonymes](#anonymous-users). - Si votre application dispose (ou disposera) d'une authentification backend, consultez la [section sur les utilisateurs identifiés](#identified-users). :::tip **Concepts clés** : - Les **profils** sont les entités nécessaires au fonctionnement du SDK. Adapty les crée automatiquement. Ils peuvent être anonymes (sans identifiant utilisateur client) ou identifiés (avec un identifiant utilisateur client). - Les **identifiants utilisateur client** sont des identifiants optionnels **que vous créez** pour permettre à Adapty de lier vos utilisateurs à leurs profils Adapty. ::: Voici les différences entre les utilisateurs anonymes et les utilisateurs identifiés : | | Utilisateurs anonymes | Utilisateurs identifiés | |-----------------------------|-------------------------------------------------------------------|-------------------------------------------------------------------------------------------| | **Gestion des achats** | Restauration des achats au niveau du store | Historique des achats maintenu sur tous les appareils via leur identifiant utilisateur client | | **Gestion des profils** | Nouveau profil à chaque réinstallation | Le même profil entre les sessions et les appareils | | **Persistance des données** | Les données des utilisateurs anonymes sont liées à l'appareil/installation | Les données des utilisateurs identifiés persistent entre les appareils et les sessions | ## Utilisateurs anonymes \{#anonymous-users\} Si vous n'avez pas d'authentification backend, **vous n'avez pas besoin de gérer l'authentification dans le code de l'application** : 1. Lors de l'activation du SDK au premier lancement de l'application, Adapty **crée un nouveau profil pour l'utilisateur**. 2. Lorsque l'utilisateur effectue un achat dans l'application, cet achat est **associé à son profil Adapty et à son compte store**. 3. Lorsque l'utilisateur **réinstalle** l'application ou l'installe sur un **nouvel appareil**, Adapty **crée un nouveau profil vide lors de l'activation**. 4. Si l'utilisateur a déjà effectué des achats dans votre application, ceux-ci sont, par défaut, automatiquement synchronisés depuis l'App Store lors de l'activation du SDK. :::note Les restaurations depuis une sauvegarde se comportent différemment des réinstallations. Par défaut, lorsqu'un utilisateur restaure depuis une sauvegarde, le SDK conserve les données en cache et ne crée pas de nouveau profil. Vous pouvez configurer ce comportement via le paramètre `clearDataOnBackup`. [En savoir plus](sdk-installation-capacitor#clear-data-on-backup-restore). ::: ## Utilisateurs identifiés \{#identified-users\} - Si un profil n'a pas encore d'identifiant utilisateur client (c'est-à-dire que **l'utilisateur n'est pas connecté**), lorsque vous envoyez un identifiant utilisateur client, celui-ci est associé à ce profil. - S'il s'agit d'une **réinstallation, d'une connexion ou d'une installation sur un nouvel appareil**, et que vous avez déjà envoyé l'identifiant utilisateur client auparavant, aucun nouveau profil n'est créé. On bascule plutôt vers le profil existant associé à cet identifiant. Vous avez deux options pour identifier les utilisateurs dans l'application : - [**Lors de la connexion/inscription :**](#during-loginsignup) Si les utilisateurs se connectent après le démarrage de votre application, appelez `identify()` avec un identifiant utilisateur client lors de leur authentification. - [**Lors de l'activation du SDK :**](#during-the-sdk-activation) Si vous disposez déjà d'un identifiant utilisateur client au moment du lancement de l'application, envoyez-le lors de l'appel à `activate()`. :::important Par défaut, lorsqu'Adapty reçoit un achat d'un identifiant utilisateur client qui est actuellement associé à un autre identifiant utilisateur client, le niveau d'accès est partagé, de sorte que les deux profils disposent d'un accès payant. Vous pouvez configurer ce paramètre pour transférer l'accès payant d'un profil à un autre ou désactiver complètement le partage. Consultez l'[article](general#6-sharing-paid-access-between-user-accounts) pour plus de détails. ::: ### Lors de la connexion/inscription \{#during-loginsignup\} Si vous identifiez les utilisateurs après le lancement de l'application (par exemple, après leur connexion ou leur inscription), utilisez la méthode `identify` pour définir leur identifiant utilisateur client. - Si vous **n'avez jamais utilisé cet identifiant utilisateur client auparavant**, Adapty le liera automatiquement au profil actuel. - Si vous **avez déjà utilisé cet identifiant utilisateur client pour identifier l'utilisateur**, Adapty basculera vers le profil associé à cet identifiant. :::tip Lors de la création d'un identifiant utilisateur client, enregistrez-le avec les données de votre utilisateur afin de pouvoir envoyer le même identifiant lorsqu'il se connecte depuis de nouveaux appareils ou réinstalle votre application. ::: Utilisez toujours `await` avec `identify` avant d'appeler d'autres méthodes du SDK. Les appels simultanés produisent `#3006 profileWasChanged` ou atterrissent sur le profil anonyme. Voir [Ordre des appels dans le SDK Capacitor](capacitor-sdk-call-order). ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` ### Lors de l'activation du SDK \{#during-the-sdk-activation\} Si vous connaissez déjà un identifiant utilisateur client au moment d'activer le SDK, vous pouvez le transmettre dans la méthode `activate` plutôt que d'appeler `identify` séparément. Si vous connaissez un identifiant utilisateur client mais ne le définissez qu'après l'activation, cela signifie qu'à l'activation, Adapty créera un nouveau profil vide et ne basculera vers le profil existant qu'après l'appel à `identify`. Vous pouvez passer soit un identifiant utilisateur client existant (que vous avez déjà utilisé) soit un nouveau. Si vous en passez un nouveau, le profil créé lors de l'activation sera automatiquement lié à cet identifiant. :::tip Pour exclure les profils vides créés des analyses du tableau de bord, accédez à **App settings** et configurez la [**Installs definition for analytics**](general#4-installs-definition-for-analytics). ::: ```typescript showLineNumbers await adapty.activate({ apiKey: "YOUR_PUBLIC_SDK_KEY", params: { customerUserId: "YOUR_USER_ID" } }); ``` ### Déconnecter les utilisateurs \{#log-users-out\} Si votre application comporte un bouton de déconnexion, utilisez la méthode `logout`. Cela crée un nouvel identifiant de profil anonyme pour l'utilisateur. ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` :::info Pour reconnecter les utilisateurs à l'application, utilisez la méthode `identify`. ::: ### Autoriser les achats sans connexion \{#allow-purchases-without-login\} Si vos utilisateurs peuvent effectuer des achats avant et après leur connexion à votre application, aucune configuration supplémentaire n'est nécessaire : Voici comment cela fonctionne : 1. Lorsqu'un utilisateur déconnecté effectue un achat, Adapty l'associe à son identifiant de profil anonyme. 2. Lorsque l'utilisateur se connecte à son compte, Adapty bascule vers son profil identifié. - S'il s'agit d'un identifiant utilisateur client existant (déjà lié à un profil), Adapty synchronise automatiquement ses transactions. - S'il s'agit d'un nouvel identifiant utilisateur client (par exemple, l'achat a été effectué avant l'inscription), Adapty attribue l'identifiant utilisateur client au profil actuel, de sorte que tout l'historique des achats est conservé. --- # File: adapty-sdk-integration-skill-capacitor --- --- title: "Intégrer Adapty dans votre application Capacitor avec la compétence d'intégration SDK" description: "Utilisez la compétence adapty-sdk-integration pour intégrer le SDK Adapty dans votre application Capacitor de bout en bout avec votre outil de codage IA." --- :::important La compétence est en version bêta. Si elle se bloque ou se comporte de manière inattendue, suivez le [guide d'intégration étape par étape](adapty-cursor-capacitor) à la place — il guide votre outil IA à travers chaque étape avec la documentation appropriée. ::: La [compétence adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatise l'intégration Adapty de bout en bout : configuration du tableau de bord, installation du SDK, paywall et vérification à chaque étape. Elle détecte automatiquement votre plateforme et récupère la documentation Adapty pertinente à chaque étape. **Outils compatibles** : Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI. Pour installer, choisissez le formulaire correspondant à votre outil. La liste complète se trouve dans le [README de la compétence](https://github.com/adaptyteam/adapty-sdk-integration-skill). **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 ou tout autre outil** — utilisez la [CLI skills](https://skills.sh) (notez que les compétences installées de cette façon ne se mettent pas à jour automatiquement) : ``` npx skills add adaptyteam/adapty-sdk-integration-skill ``` Vous pouvez également cloner le dépôt et copier `skills/adapty-sdk-integration/` dans le répertoire des compétences de votre outil. Après l'installation, exécutez la compétence dans votre projet : ``` /adapty-sdk-integration ``` La compétence pose quelques questions de configuration, puis guide à travers la configuration du tableau de bord, l'installation du SDK, le paywall et la vérification. --- # File: adapty-cursor-capacitor --- --- title: "Intégrer Adapty dans votre application Capacitor avec l'aide de l'IA" description: "Un guide étape par étape pour intégrer Adapty dans votre application Capacitor en utilisant Cursor, Context7, ChatGPT, Claude ou d'autres outils IA." --- Ce guide vous accompagne pas à pas dans l'intégration d'Adapty dans votre application Capacitor à l'aide d'un outil de codage IA — il vous suffit de lui fournir la bonne documentation Adapty dans le bon ordre. 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. ## Avant de commencer : configuration du tableau de bord \{#before-you-start-dashboard-setup\} Adapty nécessite quelques étapes de configuration dans le tableau de bord avant d'écrire du code avec le SDK. Vous pouvez le faire avec un skill LLM interactif, ou manuellement via le Dashboard. ### Approche par compétence (recommandée) \{#skill-approach-recommended\} La compétence Adapty CLI permet à votre LLM de configurer votre application, vos produits, vos niveaux d'accès, vos paywalls et vos placements directement — sans ouvrir le Dashboard à chaque étape. Il vous suffit de [connecter vos stores](integrate-payments) dans le Dashboard. ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` Une fois la compétence ajoutée, exécutez `/adapty-cli` dans votre agent. Il vous guidera à chaque étape — y compris lorsqu'il faudra ouvrir le Dashboard pour connecter vos stores. ### Approche via le tableau de bord \{#dashboard-approach\} Si vous préférez tout configurer manuellement, voici ce dont vous avez besoin avant d'écrire du code. Votre LLM ne peut pas rechercher les valeurs du tableau de bord à votre place — vous devrez les fournir vous-même. 1. **Connectez vos stores** : Dans l'Adapty Dashboard, accédez à **App settings → General**. Connectez l'App Store et Google Play si votre application Capacitor cible les deux plateformes. C'est indispensable pour que les achats fonctionnent. [Connecter les stores](integrate-payments) 2. **Copiez votre clé SDK publique** : dans l'Adapty Dashboard, rendez-vous dans **App settings → General**, puis repérez la section **API keys**. Dans le code, c'est la chaîne que vous passez à `adapty.activate()`. 3. **Créez au moins un produit** : dans l'Adapty Dashboard, accédez à la page **Products**. Vous ne référencez pas les produits directement dans le code — Adapty les transmet via les paywalls. [Ajouter des produits](quickstart-products) 4. **Créez un paywall et un placement** : Dans l'Adapty Dashboard, créez un paywall sur la page **Paywalls**, puis assignez-le à un placement sur la page **Placements**. Dans le code, l'ID du placement est la chaîne que vous passez à `adapty.getFlow()`. [Créer un paywall](quickstart-paywalls) 5. **Configurez les niveaux d'accès** : Dans l'Adapty Dashboard, configurez chaque produit sur la page **Products**. Dans le code, la chaîne vérifiée est `profile.accessLevels['premium']?.isActive`. Le niveau d'accès `premium` par défaut convient à la plupart des applications. Si les utilisateurs payants ont accès à différentes fonctionnalités selon le produit (par exemple, un plan `basic` ou un plan `pro`), [créez des niveaux d'accès supplémentaires](assigning-access-level-to-a-product) avant de commencer à coder. :::tip Une fois que vous avez les cinq éléments, vous êtes prêt à écrire du code. Dites à votre LLM : « Ma clé SDK publique est X, mon identifiant de placement est Y » pour qu'il génère le code d'initialisation et de récupération de flow correct. ::: ### Configurez quand vous êtes prêt \{#set-up-when-ready\} Ces éléments ne sont pas obligatoires pour commencer à coder, mais vous en aurez besoin au fil de l'évolution de votre intégration : - **Tests A/B** : Configurez-les sur la page **Placements**. Aucune modification de code requise. [Tests A/B](ab-tests) - **Paywalls et placements supplémentaires** : Ajoutez d'autres appels `getFlow` avec des ID de placement différents. - **Intégrations analytiques** : Configurez-les sur la page **Integrations**. La configuration varie selon l'intégration. Consultez les [intégrations analytiques](analytics-integration) et les [intégrations d'attribution](attribution-integration). ## Alimentez votre LLM avec la documentation Adapty \{#feed-adapty-docs-to-your-llm\} ### Utiliser Context7 (recommandé) [Context7](https://context7.com) est un serveur MCP qui donne à votre LLM un accès direct à la documentation Adapty à jour. Votre LLM récupère automatiquement les bonnes docs en fonction de vos questions — aucun collage d'URL manuel nécessaire. Context7 fonctionne avec **Cursor**, **Claude Code**, **Windsurf** et d'autres outils compatibles MCP. Pour le configurer, exécutez : ``` npx ctx7 setup ``` Cela détecte votre éditeur et configure le serveur Context7. Pour une configuration manuelle, consultez le [dépôt GitHub Context7](https://github.com/upstash/context7). Une fois configuré, référencez la bibliothèque Adapty dans vos prompts : ``` Use the adaptyteam/adapty-docs library to look up how to install the Capacitor SDK ``` :::warning Même si Context7 supprime le besoin de coller manuellement des liens vers la documentation, l'ordre d'implémentation est important. Suivez le [guide d'implémentation](#implementation-walkthrough) ci-dessous étape par étape pour vous assurer que tout fonctionne. ::: ### Utilisez les docs en texte brut \{#use-plain-text-docs\} Vous pouvez accéder à n'importe quelle doc Adapty en texte brut Markdown. Ajoutez `.md` à la fin de son URL, ou cliquez sur **Copy for LLM** sous le titre de l'article. Par exemple : [adapty-cursor-capacitor.md](https://adapty.io/docs/fr/adapty-cursor-capacitor.md). Chaque étape du [guide d'implémentation](#implementation-walkthrough) ci-dessous inclut un bloc « Envoyer à votre LLM » avec des liens `.md` à coller. Pour accéder à plus de documentation en une seule fois, consultez les [fichiers d'index et sous-ensembles par plateforme](#plain-text-doc-index-files) ci-dessous. ## Implémentation pas à pas \{#implementation-walkthrough\} Le reste de ce guide vous accompagne à travers l'intégration d'Adapty dans l'ordre d'implémentation. Chaque étape inclut la documentation à envoyer à votre LLM, ce que vous devriez obtenir une fois terminé, et les problèmes courants. ### Planifiez votre intégration \{#plan-your-integration\} Avant de vous lancer dans le code, demandez à votre LLM d'analyser votre projet et de créer un plan d'implémentation. Si votre outil IA dispose d'un mode planification (comme le mode plan de Cursor ou de Claude Code), utilisez-le pour que le LLM puisse lire à la fois la structure de votre projet et la documentation Adapty avant d'écrire quoi que ce soit. Indiquez à votre LLM l'approche que vous utilisez pour les achats — cela détermine les guides qu'il devra suivre : - [**Adapty Flow Builder**](adapty-flow-builder) : vous créez des flows dans le builder no-code d'Adapty, et le SDK les affiche automatiquement. - [**Paywalls créés manuellement**](capacitor-making-purchases) : vous construisez votre propre interface de paywall dans le code, mais utilisez toujours Adapty pour récupérer les produits et gérer les achats. - [**Mode observateur**](observer-vs-full-mode) : vous conservez votre infrastructure d'achats existante et utilisez Adapty uniquement pour les analyses et les intégrations. Vous ne savez pas lequel choisir ? Consultez le [tableau comparatif dans le guide de démarrage rapide](capacitor-quickstart-paywalls). ### Installer et configurer le SDK \{#install-and-configure-the-sdk\} Ajoutez la dépendance du SDK Adapty via npm et activez-la avec votre clé SDK publique. C'est la base — rien d'autre ne fonctionne sans elle. **Guide :** [Installer et configurer le SDK Adapty](sdk-installation-capacitor) :::info Ce guide cible le SDK Adapty Capacitor v4 (beta) — l'API présentée dans le [quickstart](capacitor-quickstart-paywalls). La v4 est une version préliminaire, alors assurez-vous que votre LLM utilise la version exacte (`npm install @adapty/capacitor@4.0.1-beta.1`) plutôt que la dernière version stable 3.x. Consultez la [section d'installation du SDK 4.0](sdk-installation-capacitor#adapty-sdk-40-beta) et le [guide de migration](migration-to-capacitor-sdk-v4). ::: Envoyez ceci à votre LLM : ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/sdk-installation-capacitor.md ``` :::tip[Checkpoint] - **Expected :** L'app se compile et s'exécute sur iOS et Android. La console affiche le log d'activation d'Adapty. - **Gotcha :** "Public API key is missing" → vérifiez que vous avez remplacé le placeholder par votre vraie clé depuis **App settings**. ::: ### Afficher les paywalls et gérer les achats \{#show-paywalls-and-handle-purchases\} Récupérez un paywall par identifiant de placement, affichez-le et gérez les événements d'achat. Les guides dont vous avez besoin dépendent de la façon dont vous gérez les achats. Testez chaque achat en sandbox au fur et à mesure — n'attendez pas la fin. Consultez [Tester les achats en sandbox](test-purchases-in-sandbox) pour les instructions de configuration. **Guides :** - [Activer les achats avec des flows (démarrage rapide)](capacitor-quickstart-paywalls) - [Récupérer les flows et paywalls](capacitor-get-pb-paywalls) - [Afficher les flows et paywalls](capacitor-present-paywalls) - [Gérer les événements](capacitor-handling-events) - [Répondre aux actions](capacitor-handle-paywall-actions) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/capacitor-quickstart-paywalls.md - https://adapty.io/docs/fr/capacitor-get-pb-paywalls.md - https://adapty.io/docs/fr/capacitor-present-paywalls.md - https://adapty.io/docs/fr/capacitor-handling-events.md - https://adapty.io/docs/fr/capacitor-handle-paywall-actions.md ``` :::tip[Checkpoint] - **Attendu :** Le flow s'affiche avec vos produits configurés. Appuyer sur un produit déclenche la boîte de dialogue d'achat sandbox. - **À surveiller :** Flow vide ou erreur `getFlow` → vérifiez que l'ID du placement correspond exactement à celui du tableau de bord et qu'une audience est bien assignée au placement. ::: **Guides :** - [Activer les achats dans votre paywall personnalisé (démarrage rapide)](capacitor-quickstart-manual) - [Récupérer les paywalls et les produits](fetch-paywalls-and-products-capacitor) - [Afficher un paywall conçu avec Remote Config](present-remote-config-paywalls-capacitor) - [Effectuer des achats](capacitor-making-purchases) - [Restaurer des achats](capacitor-restore-purchase) ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/capacitor-quickstart-manual.md - https://adapty.io/docs/fr/fetch-paywalls-and-products-capacitor.md - https://adapty.io/docs/fr/present-remote-config-paywalls-capacitor.md - https://adapty.io/docs/fr/capacitor-making-purchases.md - https://adapty.io/docs/fr/capacitor-restore-purchase.md ``` :::tip[Checkpoint] - **Attendu :** Votre paywall personnalisé affiche les produits récupérés depuis Adapty. Appuyer sur un produit déclenche la boîte de dialogue d'achat sandbox. - **Problème fréquent :** Tableau de produits vide → vérifiez que le paywall a des produits assignés dans le tableau de bord et que le placement a une audience. ::: **Guides :** - [Présentation du mode Observer](observer-vs-full-mode) - [Implémenter le mode Observer](implement-observer-mode-capacitor) - [Signaler les transactions en mode Observer](report-transactions-observer-mode-capacitor) Envoyez ceci à votre LLM : ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/observer-vs-full-mode.md - https://adapty.io/docs/fr/implement-observer-mode-capacitor.md - https://adapty.io/docs/fr/report-transactions-observer-mode-capacitor.md ``` :::tip[Checkpoint] - **Résultat attendu :** Après un achat sandbox via votre flux d'achat existant, la transaction apparaît dans l'**Event Feed** du tableau de bord Adapty. - **Piège courant :** Aucun événement → vérifiez que vous signalez bien les transactions à Adapty et que les notifications serveur sont configurées pour les deux stores. ::: ### Vérifier le statut de l'abonnement \{#check-subscription-status\} Après un achat, vérifiez le profil utilisateur pour un niveau d'accès actif afin de contrôler l'accès au contenu premium. **Guide :** [Vérifier le statut de l'abonnement](capacitor-check-subscription-status) Envoyez ceci à votre LLM : ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/capacitor-check-subscription-status.md ``` :::tip[Checkpoint] - **Attendu :** Après un achat sandbox, `profile.accessLevels['premium']?.isActive` renvoie `true`. - **Point d'attention :** `accessLevels` vide après un achat → vérifiez que le produit a bien un niveau d'accès assigné dans le tableau de bord. ::: ### Identifier les utilisateurs \{#identify-users\} Associez les comptes utilisateurs de votre application aux profils Adapty pour que les achats persistent d'un appareil à l'autre. :::important Ignorez cette étape si votre application ne nécessite pas d'authentification. ::: **Guide :** [Identifier les utilisateurs](capacitor-quickstart-identify) Envoyez ceci à votre LLM : ``` Read these Adapty docs before writing code: - https://adapty.io/docs/fr/capacitor-quickstart-identify.md ``` :::tip[Checkpoint] - **Attendu :** Après avoir appelé `adapty.identify()`, la section **Profiles** du tableau de bord affiche votre identifiant utilisateur personnalisé. - **Attention :** Appelez `identify` après l'activation mais avant de récupérer les paywalls pour éviter une attribution de profil anonyme. ::: ### Préparer la mise en production \{#prepare-for-release\} Une fois votre intégration validée en sandbox, parcourez la checklist de mise en production pour vous assurer que tout est prêt. **Guide :** [Checklist de mise en production](release-checklist) Envoyez ceci à votre LLM : ``` Read these Adapty docs before releasing: - https://adapty.io/docs/fr/release-checklist.md ``` :::tip[Checkpoint] - **Attendu :** Tous les éléments de la liste de contrôle sont confirmés : connexions au store, notifications serveur, flux d'achat, vérifications du niveau d'accès et exigences de confidentialité. - **Point d'attention :** Notifications serveur manquantes → configurez les App Store Server Notifications dans **App settings → iOS SDK** et les Google Play Real-Time Developer Notifications dans **App settings → Android SDK**. ::: ## Fichiers d'index en texte brut \{#plain-text-doc-index-files\} Si vous souhaitez fournir à votre LLM un contexte plus large au-delà des pages individuelles, nous hébergeons des fichiers d'index qui listent ou regroupent toute la documentation Adapty : - [`llms.txt`](https://adapty.io/docs/fr/llms.txt) : Liste toutes les pages avec des liens `.md`. Un [standard émergent](https://llmstxt.org/) pour rendre les sites web accessibles aux LLMs. Notez que pour certains agents IA (par ex. ChatGPT), vous devrez télécharger `llms.txt` et le joindre à la conversation en tant que fichier. - [`llms-full.txt`](https://adapty.io/docs/fr/llms-full.txt) : L'intégralité de la documentation Adapty regroupée en un seul fichier. Très volumineux — à utiliser uniquement lorsque vous avez besoin d'une vue d'ensemble complète. - Fichiers spécifiques à Capacitor [`capacitor-llms.txt`](https://adapty.io/docs/fr/capacitor-llms.txt) et [`capacitor-llms-full.txt`](https://adapty.io/docs/fr/capacitor-llms-full.txt) : Sous-ensembles propres à la plateforme, moins lourds en tokens que le site complet. --- # File: capacitor-paywalls --- --- title: "Flows et paywalls - Capacitor" description: "Affichez et gérez les flows et paywalls créés avec l'Adapty Flow Builder ou le Paywall Builder dans votre application Capacitor." --- ## Afficher des paywalls \{#display-paywalls\} ### Adapty Flow Builder & Paywall Builder \{#adapty-flow-builder--paywall-builder\} :::tip Pour démarrer rapidement avec les flows et paywalls Adapty, consultez notre [guide de démarrage rapide](capacitor-quickstart-paywalls). ::: ### Implémenter des paywalls manuellement \{#implement-paywalls-manually\} Pour d'autres guides sur l'implémentation des paywalls et la gestion des achats manuellement, consultez la [catégorie](capacitor-implement-paywalls-manually). ## Fonctionnalités utiles \{#useful-features\} --- # File: capacitor-get-pb-paywalls --- --- title: "Obtenir des flows et des paywalls - Capacitor" description: "Récupérez les flows et les paywalls depuis Adapty dans votre application Capacitor." --- Après avoir [conçu votre flow ou votre paywall dans le Paywall Builder](adapty-paywall-builder), vous pouvez l'afficher dans votre application mobile. La première étape consiste à récupérer le flow ou le paywall associé au placement et à sa configuration de vue, comme décrit ci-dessous. Notez que cette rubrique concerne les flows et les paywalls personnalisés avec le Paywall Builder. Si vous implémentez vos paywalls manuellement, consultez la rubrique [Récupérer les paywalls et les produits pour les paywalls Remote Config dans votre application mobile](fetch-paywalls-and-products-capacitor). :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base. :::
Avant de commencer à afficher des flows et des paywalls dans votre application mobile (cliquez pour agrandir) 1. [Créez vos produits](create-product) dans l'Adapty Dashboard. 2. [Créez un flow/paywall et intégrez-y les produits](create-paywall) dans l'Adapty Dashboard. 3. [Créez des placements et intégrez-y votre flow/paywall](create-placement) dans l'Adapty Dashboard. 4. Installez le [SDK Adapty](sdk-installation-capacitor) dans votre application mobile.
## Récupérer un flow/paywall \{#fetch-flowpaywall\} Si vous avez conçu un flow ou un paywall avec le Flow Builder ou le Paywall Builder, vous n'avez pas à vous soucier de son rendu dans le code de votre application mobile pour l'afficher à l'utilisateur. Un tel flow ou paywall contient à la fois ce qui doit être affiché et comment l'afficher. Vous devez néanmoins récupérer son ID via le placement, sa configuration de vue, puis le présenter dans votre application mobile. Récupérez le flow ou le paywall et créez sa [vue](capacitor-get-pb-paywalls#fetch-the-view-configuration) le plus tôt possible — idéalement bien avant de l'afficher. La méthode `createFlowView` charge la configuration de la vue et lance le téléchargement et la mise en cache de ses images en arrière-plan. Plus tôt vous l'appelez, plus ces téléchargements ont de temps pour se terminer. Au moment où vous affichez le flow ou le paywall, sa configuration et ses images peuvent déjà être en cache et prêtes à être affichées. Pour obtenir un flow ou un paywall, utilisez la méthode `getFlow` : ```typescript showLineNumbers try { const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested flow/paywall } catch (error) { // handle the error } ``` Paramètres : | Paramètre | Présence | Description | |-------------------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements) souhaité. C'est la valeur que vous avez indiquée lors de la création d'un placement dans l'Adapty Dashboard. | | **fetchPolicy** | par défaut : `'reload_revalidating_cache_data'` |

Passé dans l'objet optionnel `params`. Par défaut, le SDK tente de charger les données depuis le serveur et retourne les données en cache en cas d'échec. Nous recommandons cette option, car elle garantit que vos utilisateurs reçoivent toujours les données les plus récentes.

Cependant, si vous pensez que vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour retourner les données en cache si elles existent. Dans ce cas, les utilisateurs ne disposeront peut-être pas des toutes dernières données, mais bénéficieront de temps de chargement plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sûr de l'utiliser pendant la session pour éviter les requêtes réseau.

Notez que le cache reste intact après le redémarrage de l'application et n'est effacé qu'à la réinstallation de l'application ou via un nettoyage manuel.

Le SDK Adapty stocke les paywalls localement sur deux couches : le cache mis à jour régulièrement décrit ci-dessus et les [paywalls de secours](fallback-paywalls). Nous utilisons également un CDN pour récupérer les paywalls plus rapidement ainsi qu'un serveur de secours indépendant en cas d'indisponibilité du CDN. Ce système est conçu pour vous garantir toujours la dernière version de vos paywalls tout en assurant la fiabilité, même lorsque la connexion internet est limitée.

| | **loadTimeoutMs** | par défaut : 5 sec |

Passé dans l'objet optionnel `params`. Cette valeur limite le délai d'expiration de cette méthode. Si le délai est atteint, les données en cache ou le fallback local sont retournés.

Notez que dans de rares cas, cette méthode peut expirer légèrement après le délai indiqué dans `loadTimeoutMs`, car l'opération peut comprendre différentes requêtes en coulisse.

| **N'inscrivez pas les IDs de produits en dur dans le code.** Le seul ID à coder en dur est l'ID de placement. Les flows et les paywalls étant configurés à distance, le nombre de produits et les offres disponibles peuvent changer à tout moment. Votre application doit gérer ces changements de manière dynamique — si un paywall retourne deux produits aujourd'hui et trois demain, tous doivent s'afficher sans modification du code. Paramètres de réponse : | Paramètre | Description | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Un objet `AdaptyFlow` contenant les identifiants du flow (`id`, `variationId`), son nom, son placement, ses variantes de paywall (`paywalls`), ainsi que les Remote Configs éventuels (`remoteConfigs`). | ## Récupérer la configuration de la vue \{#fetch-the-view-configuration\} :::important Assurez-vous d'activer le bouton **Show on device** dans le builder. Si cette option n'est pas activée, la configuration de la vue ne sera pas disponible à la récupération. ::: Si le placement a été conçu dans le **Flow Builder** ou le **Paywall Builder**, Adapty génère l'interface utilisateur pour vous. Créez la vue avec `createFlowView`, puis [affichez le flow ou le paywall](capacitor-present-paywalls). Si le placement est un paywall personnalisé sans interface Builder, [gérez-le comme un paywall Remote Config](present-remote-config-paywalls-capacitor) à la place. Dans le SDK Capacitor, appelez directement `createFlowView` — il n'est pas nécessaire de récupérer d'abord la configuration de la vue. :::warning Le résultat de la méthode `createFlowView` ne peut être utilisé qu'une seule fois. Si vous en avez besoin à nouveau, appelez de nouveau la méthode `createFlowView`. L'appeler deux fois sans recréer la vue peut entraîner une erreur. ::: ```typescript showLineNumbers try { const view = await createFlowView(flow); } catch (error) { // handle the error } ``` Paramètres : | Paramètre | Présence | Description | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | obligatoire | Un objet `AdaptyFlow` permettant d'obtenir un contrôleur pour le flow/paywall souhaité. | | **locale** | optionnel | L'identifiant de la [localisation du flow](add-paywall-locale-in-adapty-paywall-builder) à utiliser pour afficher la vue — par exemple, `en` ou `pt-br`. Si omis, la vue s'affiche en `en`, ou dans la localisation par défaut du flow si celui-ci ne dispose pas de version `en`. Voir [Localisations et codes de langue](capacitor-localizations-and-locale-codes). | | **customTags** | optionnel | Définit un dictionnaire de balises personnalisées et leurs valeurs résolues. Les balises personnalisées servent de placeholders dans le contenu, remplacées dynamiquement par des chaînes spécifiques pour personnaliser le contenu du flow/paywall. Consultez la rubrique sur les balises personnalisées dans le Paywall Builder pour plus de détails. | | **prefetchProducts** | optionnel | Activez cette option pour optimiser le moment d'affichage des produits à l'écran. Lorsque la valeur est `true`, AdaptyUI récupère automatiquement les produits nécessaires. Par défaut : `true`. | | **android.enableSafeArea** | optionnel | Android uniquement (ignoré sur iOS). Imbriqué sous la clé `android`. Lorsque la valeur est `true`, la vue du flow applique les marges de zone sécurisée. Par défaut : `true`. La valeur par défaut convient à la plupart des cas. | :::note Si vous utilisez plusieurs langues, découvrez comment ajouter une [localisation de flow](add-paywall-locale-in-adapty-paywall-builder) et comment utiliser correctement les codes de langue [ici](capacitor-localizations-and-locale-codes). ::: Une fois que vous avez la vue, [affichez le flow/paywall](capacitor-present-paywalls). ## Récupérer un flow ou un paywall pour l'audience par défaut afin d'accélérer le chargement \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} En général, les flows et les paywalls sont récupérés presque instantanément, donc vous n'avez pas à vous inquiéter d'accélérer ce processus. Cependant, si vous avez de nombreuses audiences et placements, et que vos utilisateurs disposent d'une connexion internet faible, la récupération d'un flow ou d'un paywall peut prendre plus de temps que souhaité. Dans ce cas, vous pourriez vouloir afficher un flow ou un paywall par défaut pour garantir une expérience utilisateur fluide plutôt que de ne rien afficher du tout. Pour y remédier, vous pouvez utiliser la méthode `getFlowForDefaultAudience`, qui récupère le flow ou le paywall du placement spécifié pour l'audience **All Users**. Il est toutefois essentiel de comprendre que l'approche recommandée est de récupérer le flow ou le paywall via la méthode `getFlow`, comme décrit dans la section [Récupérer le flow/paywall](#fetch-flowpaywall) ci-dessus. :::warning Pourquoi nous recommandons d'utiliser `getFlow` La méthode `getFlowForDefaultAudience` présente quelques inconvénients majeurs : - **Problèmes potentiels de rétrocompatibilité** : si vous devez afficher des paywalls différents selon les versions de l'application (version actuelle et futures versions), vous risquez de rencontrer des difficultés. Vous devrez soit concevoir des paywalls compatibles avec la version actuelle (legacy), soit accepter que les utilisateurs de cette version puissent rencontrer des problèmes avec des paywalls qui ne s'affichent pas. - **Perte de ciblage** : tous les utilisateurs verront le même paywall conçu pour l'audience **All Users**, ce qui signifie que vous perdez le ciblage personnalisé (notamment par pays, attribution marketing ou attributs personnalisés). Si vous acceptez ces inconvénients pour bénéficier d'une récupération de flow ou de paywall plus rapide, utilisez la méthode `getFlowForDefaultAudience` comme suit. Sinon, restez sur `getFlow` décrit [ci-dessus](#fetch-flowpaywall). ::: ```typescript showLineNumbers try { const flow = await adapty.getFlowForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested flow/paywall } catch (error) { // handle the error } ``` | Paramètre | Présence | Description | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | requis | L'identifiant du [Placement](placements). Il s'agit de la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **fetchPolicy** | défaut : `'reload_revalidating_cache_data'` |

Passé dans l'objet optionnel `params`. Par défaut, le SDK tente de charger les données depuis le serveur et retourne les données en cache en cas d'échec. Nous recommandons cette option, car elle garantit que vos utilisateurs reçoivent toujours les données les plus récentes.

Cependant, si vous pensez que vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour retourner les données en cache si elles existent. Dans ce cas, les utilisateurs risquent de ne pas obtenir les toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sûr de l'utiliser pendant la session pour éviter les requêtes réseau.

Notez que le cache reste intact après un redémarrage de l'application et n'est effacé que lors d'une réinstallation ou par un nettoyage manuel.

| ## Personnaliser les assets \{#customize-assets\} Pour personnaliser les images et vidéos de votre flow/paywall, implémentez des assets personnalisés. Les images et vidéos hero ont des IDs prédéfinis : `hero_image` et `hero_video`. Dans un bundle d'assets personnalisé, vous ciblez ces éléments par leurs IDs et personnalisez leur comportement. Pour les autres images et vidéos, vous devez [définir un ID personnalisé](custom-media) dans l'Adapty Dashboard. Par exemple, vous pouvez : - Afficher une image ou vidéo différente à certains utilisateurs. - Afficher une image de prévisualisation locale pendant le chargement d'une image principale distante. - Afficher une image de prévisualisation avant de lancer une vidéo. Voici un exemple de la façon dont vous pouvez fournir des ressources personnalisées via un dictionnaire simple : ```typescript showLineNumbers const customAssets: Record = { '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 Si un asset est introuvable, le flow/paywall reviendra à son apparence par défaut. :::
Après avoir [conçu la partie visuelle de votre paywall](adapty-paywall-builder) avec le nouveau Paywall Builder dans l'Adapty Dashboard, vous pouvez l'afficher dans votre application mobile. La première étape de ce processus consiste à récupérer le paywall associé au placement et sa configuration d'affichage, comme décrit ci-dessous. Veuillez noter que cette rubrique concerne les paywalls personnalisées avec Paywall Builder. Pour savoir comment récupérer les paywalls avec Remote Config, consultez la rubrique [Récupérer les paywalls et produits pour les paywalls Remote Config dans votre application mobile](fetch-paywalls-and-products-capacitor).
Avant de commencer à afficher des paywalls dans votre application mobile (cliquez pour développer) 1. [Créez vos produits](create-product) dans l'Adapty Dashboard. 2. [Créez un paywall et intégrez-y les produits](create-paywall) dans l'Adapty Dashboard. 3. [Créez des placements et intégrez-y votre paywall](create-placement) dans l'Adapty Dashboard. 4. Installez le [SDK Adapty](sdk-installation-capacitor) dans votre application mobile.
## Récupérer un paywall conçu avec le Paywall Builder \{#fetch-paywall-designed-with-paywall-builder\} Si vous avez [conçu un paywall avec le Paywall Builder](adapty-paywall-builder), vous n'avez pas à vous soucier de son rendu dans le code de votre application mobile pour l'afficher à l'utilisateur. Un tel paywall contient à la fois ce qui doit être affiché et comment cela doit l'être. Vous devez néanmoins récupérer son identifiant via le placement, sa configuration d'affichage, puis le présenter dans votre application mobile. Pour garantir des performances optimales, il est essentiel de récupérer le paywall et sa [configuration de vue](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) le plus tôt possible, afin de laisser suffisamment de temps aux images de se télécharger avant de les présenter à l'utilisateur. Pour obtenir un paywall, utilisez la méthode `getPaywall` : ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // the requested paywall } catch (error) { // handle the error } ``` Paramètres : | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements) souhaité. C'est la valeur que vous avez indiquée lors de la création d'un placement dans l'Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la [localisation du paywall](add-paywall-locale-in-adapty-paywall-builder). Ce paramètre doit être un code de langue composé d'un ou deux sous-tags séparés par le caractère moins (**-**). Le premier sous-tag désigne la langue, le second la région.

Exemple : `en` signifie anglais, `pt-br` représente le portugais brésilien.

Consultez [Localisations et codes de langue](localizations-and-locale-codes) pour plus d'informations sur les codes de langue et leur utilisation recommandée.

| | **params** | optionnel | Paramètres supplémentaires pour récupérer le paywall. | **Ne codez pas en dur les ID de produits.** Le seul ID à coder en dur est l'ID de placement. Les paywalls étant configurés à distance, le nombre de produits et les offres disponibles peuvent changer à tout moment. Votre application doit gérer ces changements de façon dynamique — si un paywall renvoie deux produits aujourd'hui et trois demain, affichez-les tous sans modifier le code. Paramètres de réponse : | Paramètre | Description | | :-------- |:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Un objet [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) contenant une liste d'identifiants de produits, l'identifiant du paywall, le Remote Config et plusieurs autres propriétés. | ## Récupérer la configuration d'affichage d'un paywall conçu avec le Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Assurez-vous d'activer le bouton **Show on device** dans le Paywall Builder. Si cette option n'est pas activée, la configuration d'affichage ne pourra pas être récupérée. ::: Après avoir récupéré le paywall, vérifiez s'il inclut une `ViewConfiguration`, ce qui indique qu'il a été créé avec Paywall Builder. Cela vous guidera sur la façon d'afficher le paywall. Si la `ViewConfiguration` est présente, traitez-le comme un paywall Paywall Builder ; sinon, [gérez-le comme un paywall Remote Config](present-remote-config-paywalls-capacitor). Dans le SDK Capacitor, appelez directement la méthode `createPaywallView` sans récupérer manuellement la configuration de vue au préalable. :::warning Le résultat de la méthode `createPaywallView` ne peut être utilisé qu'une seule fois. Si vous avez besoin de l'utiliser à nouveau, appelez à nouveau la méthode `createPaywallView`. ::: ```typescript showLineNumbers if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { // use your custom logic } ``` Paramètres : | Paramètre | Présence | Description | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | required | Un objet `AdaptyPaywall` pour obtenir un contrôleur pour le paywall souhaité. | | **customTags** | optional | Définit un dictionnaire de tags personnalisés et leurs valeurs résolues. Les tags personnalisés servent de placeholders dans le contenu du paywall, remplacés dynamiquement par des chaînes spécifiques pour un contenu personnalisé. Consultez la rubrique Custom tags in paywall builder pour plus de détails. | | **prefetchProducts** | optional | Activez cette option pour optimiser le moment d'affichage des produits à l'écran. Lorsque la valeur est `true`, AdaptyUI récupère automatiquement les produits nécessaires. Par défaut : `false`. | :::note Si vous utilisez plusieurs langues, découvrez comment ajouter une [localisation dans le Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) et comment utiliser correctement les codes de locale [ici](capacitor-localizations-and-locale-codes). ::: Une fois la vue disponible, [affichez le paywall](capacitor-present-paywalls). ## Obtenir un paywall pour l'audience par défaut afin de l'afficher plus rapidement \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} En général, les paywalls se chargent presque instantanément, vous n'avez donc pas à vous soucier d'optimiser ce processus. Cependant, si vous avez de nombreuses audiences et paywalls et que vos utilisateurs disposent d'une connexion internet faible, le chargement d'un paywall peut prendre plus de temps que souhaité. Dans ce cas, vous pouvez afficher un paywall par défaut pour garantir une expérience fluide plutôt que de ne rien afficher du tout. Pour remédier à cela, vous pouvez utiliser la méthode `getPaywallForDefaultAudience`, qui récupère le paywall du placement spécifié pour l'audience **All Users**. Il est toutefois essentiel de comprendre que l'approche recommandée est de récupérer le paywall via la méthode `getPaywall`, comme décrit dans la section [Récupérer les informations du paywall](#fetch-paywall-designed-with-paywall-builder) ci-dessus. :::warning Pourquoi nous recommandons d'utiliser `getPaywall` La méthode `getPaywallForDefaultAudience` présente quelques inconvénients majeurs : - **Problèmes potentiels de compatibilité descendante** : si vous devez afficher des paywalls différents selon les versions de l'application (version actuelle et versions futures), vous devrez soit concevoir des paywalls compatibles avec la version actuelle (legacy), soit accepter que les utilisateurs de cette version puissent rencontrer des problèmes avec des paywalls non affichés. - **Perte de ciblage** : tous les utilisateurs verront le même paywall conçu pour l'audience **All Users**, ce qui signifie que vous perdez le ciblage personnalisé (y compris par pays, attribution marketing ou attributs personnalisés). Si vous acceptez ces inconvénients pour bénéficier d'une récupération plus rapide des paywalls, utilisez la méthode `getPaywallForDefaultAudience` comme suit. Sinon, utilisez `getPaywall` décrit [ci-dessus](#fetch-paywall-designed-with-paywall-builder). ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // the requested paywall } catch (error) { // handle the error } ``` | Paramètre | Présence | Description | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | requis | L'identifiant du [placement](placements). C'est la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la [localisation du paywall](add-remote-config-locale). Ce paramètre doit être un code de langue composé d'un ou plusieurs sous-tags séparés par le caractère moins (**-**). Le premier sous-tag correspond à la langue, le second à la région.

Exemple : `en` désigne l'anglais, `pt-br` le portugais brésilien.

Consultez [Localisations et codes de langue](capacitor-localizations-and-locale-codes) pour en savoir plus sur les codes de langue et nos recommandations d'utilisation.

| | **params** | optionnel | Paramètres supplémentaires pour récupérer le paywall. | ## Personnaliser les ressources \{#customize-assets\} Pour personnaliser les images et vidéos de votre paywall, utilisez des ressources personnalisées. Les images et vidéos hero ont des identifiants prédéfinis : `hero_image` et `hero_video`. Dans un bundle de ressources personnalisées, vous ciblez ces éléments par leur identifiant pour personnaliser leur comportement. Pour les autres images et vidéos, vous devez [définir un identifiant personnalisé](custom-media) dans l'Adapty Dashboard. Par exemple, vous pouvez : - Afficher une image ou une vidéo différente à certains utilisateurs. - Afficher une image de prévisualisation locale pendant le chargement d'une image principale distante. - Afficher une image de prévisualisation avant de lancer une vidéo. Voici un exemple de la façon dont vous pouvez fournir des ressources personnalisées via un simple dictionnaire : ```typescript showLineNumbers const customAssets: Record = { '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 Si une ressource est introuvable, le paywall affichera son apparence par défaut. :::
--- # File: capacitor-present-paywalls --- --- title: "Afficher les flows et les paywalls - Capacitor" description: "Présentez des flows et des paywalls aux utilisateurs dans votre app Capacitor avec Adapty." --- Si vous avez créé un flow ou un paywall dans le Flow Builder, vous n'avez pas à vous soucier de son rendu dans le code de votre app mobile pour l'afficher à l'utilisateur. Un tel flow contient à la fois ce qui doit être affiché et la façon dont cela doit l'être. Avant de commencer, assurez-vous que : 1. Vous avez [créé un flow ou un paywall](create-paywall). 2. Vous l'avez ajouté à un [placement](placements). 3. Vous avez [récupéré le flow et préparé la vue](capacitor-get-pb-paywalls). :::warning Ce guide concerne uniquement les **flows et les paywalls créés avec le Paywall Builder**, qui nécessitent le SDK v4.0 ou une version ultérieure. La procédure pour présenter des flows diffère pour les paywalls à Remote Config. - Pour présenter des **paywalls à Remote Config**, consultez [Afficher un paywall conçu avec Remote Config](present-remote-config-paywalls-capacitor). ::: Pour afficher un flow ou un paywall en tant qu'écran autonome, utilisez la méthode `view.present()` sur la `view` créée par la méthode [`createFlowView`](capacitor-get-pb-paywalls#fetch-the-view-configuration). Chaque `view` ne peut être utilisée qu'une seule fois. Si vous devez afficher le flow à nouveau, appelez `createFlowView` une nouvelle fois pour créer une nouvelle instance de `view`. :::warning Réutiliser la même `view` sans la recréer est interdit. Cela provoquera une erreur. ::: ```typescript showLineNumbers const view = await createFlowView(flow); // Optional: handle flow events (close, purchase, restore, etc) // await view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` :::important Appeler `setEventHandlers` plusieurs fois écrasera les gestionnaires que vous fournissez, remplaçant à la fois les gestionnaires par défaut et ceux précédemment définis pour ces événements spécifiques. ::: ## Configurer le style de présentation iOS \{#configure-ios-presentation-style\} Configurez la façon dont le flow est présenté sur iOS en passant le paramètre `iosPresentationStyle` à la méthode `present()`. Le paramètre accepte les valeurs `'full_screen'` (par défaut) ou `'page_sheet'`. Sur Android, les flows sont toujours affichés en plein écran. ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## Utiliser un timer défini par le développeur \{#use-developer-defined-timer\} Pour utiliser des timers définis par le développeur dans votre app mobile, utilisez le `timerId`, dans cet exemple `CUSTOM_TIMER_NY`, le **Timer ID** du timer défini par le développeur que vous avez configuré dans le tableau de bord Adapty. Cela garantit que votre app met à jour dynamiquement le timer avec la valeur correcte — par exemple `13j 09h 03m 34s` (calculée comme l'heure de fin du timer, telle que le Jour de l'An, moins l'heure actuelle). ```typescript showLineNumbers const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createFlowView(flow, { customTimers }); ``` Dans cet exemple, `CUSTOM_TIMER_NY` est le **Timer ID** du timer défini par le développeur que vous avez configuré dans le tableau de bord Adapty. Le timer garantit que votre app met à jour dynamiquement le timer avec la valeur correcte — par exemple `13j 09h 03m 34s` (calculée comme l'heure de fin du timer, telle que le Jour de l'An, moins l'heure actuelle). ## Afficher une boîte de dialogue \{#show-dialog\} Utilisez cette méthode à la place des boîtes de dialogue d'alerte natives lorsqu'une vue de flow est présentée sur Android. Sur Android, les alertes classiques apparaissent derrière la vue du flow, ce qui les rend invisibles pour les utilisateurs. Cette méthode garantit un affichage correct de la boîte de dialogue au-dessus du flow sur toutes les plateformes. ```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 } ``` ## Remplacer un abonnement par un autre \{#replace-one-subscription-with-another\} Lorsqu'un utilisateur tente d'acheter un nouvel abonnement alors qu'un autre abonnement est actif sur Android, vous pouvez contrôler la façon dont le nouvel achat doit être traité en passant des paramètres de mise à jour d'abonnement lors de la création de la vue du flow. Pour remplacer l'abonnement actuel par le nouveau, utilisez `productPurchaseParams` dans `createFlowView` avec les paramètres `oldSubVendorProductId` et `prorationMode`. ```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 }); ``` Si vous avez personnalisé un paywall à l'aide du Paywall Builder, vous n'avez pas à vous soucier de son rendu dans le code de votre app mobile pour l'afficher à l'utilisateur. Un tel paywall contient à la fois ce qui doit être affiché et la façon dont cela doit l'être. :::warning Ce guide concerne uniquement les **paywalls créés avec le Paywall Builder**. La procédure pour présenter des paywalls diffère pour les paywalls à Remote Config. Pour présenter des **paywalls à Remote Config**, consultez [Afficher un paywall conçu avec Remote Config](present-remote-config-paywalls). ::: Pour afficher un paywall, utilisez la méthode `view.present()` sur la `view` créée par la méthode [`createPaywallView`](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder). Chaque `view` ne peut être utilisée qu'une seule fois. Si vous devez afficher le paywall à nouveau, appelez `createPaywallView` une nouvelle fois pour créer une nouvelle instance de `view`. :::warning Réutiliser la même `view` sans la recréer peut provoquer une erreur. ::: ```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 } ``` ## Utiliser un timer défini par le développeur \{#use-developer-defined-timer\} Pour utiliser des timers définis par le développeur dans votre app mobile, utilisez le `timerId`, dans cet exemple `CUSTOM_TIMER_NY`, le **Timer ID** du timer défini par le développeur que vous avez configuré dans le tableau de bord Adapty. Cela garantit que votre app met à jour dynamiquement le timer avec la valeur correcte — par exemple `13j 09h 03m 34s` (calculée comme l'heure de fin du timer, telle que le Jour de l'An, moins l'heure actuelle). ```typescript showLineNumbers const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createPaywallView(paywall, { customTimers }); ``` Dans cet exemple, `CUSTOM_TIMER_NY` est le **Timer ID** du timer défini par le développeur que vous avez configuré dans le tableau de bord Adapty. Le timer garantit que votre app met à jour dynamiquement le timer avec la valeur correcte — par exemple `13j 09h 03m 34s` (calculée comme l'heure de fin du timer, telle que le Jour de l'An, moins l'heure actuelle). ## Afficher une boîte de dialogue \{#show-dialog\} Utilisez cette méthode à la place des boîtes de dialogue d'alerte natives lorsqu'une vue de paywall est présentée sur Android. Sur Android, les alertes classiques apparaissent derrière la vue du paywall, ce qui les rend invisibles pour les utilisateurs. Cette méthode garantit un affichage correct de la boîte de dialogue au-dessus du paywall sur toutes les plateformes. ```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 } ``` ## Configurer le style de présentation iOS \{#configure-ios-presentation-style\} Configurez la façon dont le paywall est présenté sur iOS en passant le paramètre `iosPresentationStyle` à la méthode `present()`. Le paramètre accepte les valeurs `'full_screen'` (par défaut) ou `'page_sheet'`. ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` --- # File: capacitor-handle-paywall-actions --- --- title: "Répondre aux actions de flow - Capacitor" description: "Gérez les actions de boutons depuis les flows et paywalls dans Capacitor avec Adapty pour une meilleure monétisation." --- Si vous créez des flows ou des paywalls avec le [Flow Builder](adapty-flow-builder) ou le [Paywall Builder](adapty-paywall-builder) d'Adapty, il est essentiel de configurer correctement les boutons : 1. Ajoutez un [bouton dans le builder](paywall-buttons) et assignez-lui une action existante ou créez un identifiant d'action personnalisé. 2. Écrivez le code dans votre application pour gérer chaque action assignée. Ce guide explique comment gérer les actions personnalisées et prédéfinies dans votre code. :::warning **Les achats, restaurations, fermetures de flows et paywalls, ainsi que l'ouverture d'URL sont gérés automatiquement.** Vous pouvez configurer leur comportement par défaut ou implémenter des réponses pour les actions personnalisées. ::: :::note Définir un handler pour un événement remplace entièrement son comportement par défaut. Les handlers que vous ne définissez pas conservent leurs valeurs par défaut. ::: ## Fermer les flows et paywalls \{#close-flows-and-paywalls\} Pour ajouter un bouton qui fermera votre flow ou paywall : 1. Dans le builder, ajoutez un bouton et assignez-lui l'action **Close**. 2. Dans le code de votre application, implémentez un handler pour l'action `close` qui ferme le flow ou le paywall. :::info Dans le SDK Capacitor, l'action `close` déclenche par défaut la fermeture du flow ou du paywall. Vous pouvez cependant modifier ce comportement dans votre code si nécessaire. Par exemple, la fermeture d'un flow peut déclencher l'ouverture d'un autre. ::: ```typescript showLineNumbers const view = await createFlowView(flow); const unsubscribe = await view.setEventHandlers({ onCloseButtonPress() { return true; // allow the flow to close }, }); ``` Sur Android, le bouton système **Back** et le geste retour déclenchent un événement `onAndroidSystemBack` distinct. Dans le SDK v4, il ne ferme plus le flow par défaut. Retournez `true` depuis le handler si vous voulez que le bouton **Back** ferme le flow : ```typescript showLineNumbers const unsubscribe = await view.setEventHandlers({ onAndroidSystemBack() { return true; // close the flow when the Back button is pressed }, }); ``` ## Ouvrir des URL depuis les flows et paywalls \{#open-urls-from-flows-and-paywalls\} :::tip Si vous souhaitez ajouter un groupe de liens (par ex., conditions d'utilisation et restauration d'achat), ajoutez un élément **Link** dans le builder et gérez-le de la même façon que les boutons avec l'action **Open URL**. ::: Pour ajouter un bouton qui ouvre un lien depuis votre flow ou paywall (par ex., **Conditions d'utilisation** ou **Politique de confidentialité**) : 1. Dans le builder, ajoutez un bouton, assignez-lui l'action **Open URL** et saisissez l'URL à ouvrir. 2. Si nécessaire, dans le code de votre application, implémentez un handler pour l'action `openUrl` qui ouvre l'URL reçue à votre façon. :::info Dans le SDK Capacitor, le fait d'appuyer sur une URL l'ouvre par défaut dans le navigateur natif : le SDK appelle `adapty.openWebUrl({ url, openIn })`, en respectant l'option **Open in** définie dans le builder, et conserve le flow ouvert. Vous pouvez cependant modifier ce comportement dans votre code si nécessaire. ::: ```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 }, }); ``` ## Gérer les actions personnalisées \{#handle-custom-actions\} Pour ajouter un bouton qui gère d'autres actions : 1. Dans le builder, ajoutez un bouton, assignez-lui l'action **Custom** et donnez-lui un identifiant. 2. Dans le code de votre application, implémentez un handler pour l'identifiant d'action que vous avez créé. Par exemple, si vous avez un autre ensemble d'offres d'abonnement ou d'achats uniques, vous pouvez ajouter un bouton qui affichera un autre flow ou paywall : ```typescript showLineNumbers const unsubscribe = await view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another flow or paywall } }, }); ``` Si vous créez des paywalls avec le Paywall Builder d'Adapty, il est essentiel de configurer correctement les boutons : 1. Ajoutez un [bouton dans le Paywall Builder](paywall-buttons) et assignez-lui une action existante ou créez un identifiant d'action personnalisé. 2. Écrivez le code dans votre application pour gérer chaque action assignée. Ce guide explique comment gérer les actions personnalisées et prédéfinies dans votre code. ## Fermer les paywalls \{#close-paywalls\} Pour ajouter un bouton qui fermera votre paywall : 1. Dans le Paywall Builder, ajoutez un bouton et assignez-lui l'action **Close**. 2. Dans le code de votre application, implémentez un handler pour l'action `close` qui ferme le paywall. :::info Dans le SDK Capacitor, l'action `close` déclenche par défaut la fermeture du paywall. Vous pouvez cependant modifier ce comportement dans votre code si nécessaire. Par exemple, la fermeture d'un paywall peut déclencher l'ouverture d'un autre. ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { console.log('User closed paywall'); return true; // Allow the paywall to close } }); ``` ## Ouvrir des URL depuis les paywalls \{#open-urls-from-paywalls\} :::tip Si vous souhaitez ajouter un groupe de liens (par ex., conditions d'utilisation et restauration d'achat), ajoutez un élément **Link** dans le Paywall Builder et gérez-le de la même façon que les boutons avec l'action **Open URL**. ::: Pour ajouter un bouton qui ouvre un lien depuis votre paywall (par ex., **Conditions d'utilisation** ou **Politique de confidentialité**) : 1. Dans le Paywall Builder, ajoutez un bouton, assignez-lui l'action **Open URL** et saisissez l'URL à ouvrir. 2. Dans le code de votre application, implémentez un handler pour l'action `openUrl` qui ouvre l'URL reçue dans un navigateur. :::info Dans le SDK Capacitor, l'action `window.open` déclenche par défaut l'ouverture de l'URL. Vous pouvez cependant modifier ce comportement dans votre code si nécessaire. ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; // Don't close the paywall }, }); ``` ## Se connecter à l'application \{#log-into-the-app\} Pour ajouter un bouton qui connecte les utilisateurs à votre application : 1. Dans le Paywall Builder, ajoutez un bouton et assignez-lui l'action **Login**. 2. Dans le code de votre application, implémentez un handler pour l'action `login` qui identifie votre utilisateur. ```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'); } } }); ``` ## Gérer les actions personnalisées \{#handle-custom-actions-1\} Pour ajouter un bouton qui gère d'autres actions : 1. Dans le Paywall Builder, ajoutez un bouton, assignez-lui l'action **Custom** et donnez-lui un identifiant. 2. Dans le code de votre application, implémentez un handler pour l'identifiant d'action que vous avez créé. Par exemple, si vous avez un autre ensemble d'offres d'abonnement ou d'achats uniques, vous pouvez ajouter un bouton qui affichera un autre paywall : ```typescript showLineNumbers const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall } }, }); ``` --- # File: capacitor-handling-events --- --- title: "Gérer les événements de flow et de paywall - Capacitor" description: "Gérez les événements de flow et de paywall dans votre application Capacitor avec le SDK d'Adapty." --- :::important Ce guide couvre la gestion des événements pour les achats, les restaurations, la sélection de produits et le rendu des flows. Vous pouvez également configurer la gestion des boutons (fermeture du flow, ouverture de liens, actions personnalisées, etc.). Consultez notre [guide sur la gestion des actions de boutons](capacitor-handle-paywall-actions) pour plus de détails. ::: Les flows et paywalls créés avec le [Flow Builder](adapty-flow-builder) n'ont pas besoin de code supplémentaire pour effectuer et restaurer des achats. Ils génèrent cependant des événements auxquels votre application peut réagir. Ces événements incluent des appuis sur des boutons (boutons de fermeture, URLs, sélections de produits, etc.) ainsi que des notifications sur les actions liées aux achats effectuées sur le flow. Découvrez comment répondre à ces événements ci-dessous. Pour contrôler ou surveiller les processus qui se déroulent sur l'écran du flow dans votre application mobile, implémentez la méthode `view.setEventHandlers` : :::important Vous ne pouvez définir qu'un seul gestionnaire par événement : appeler `setEventHandlers` plusieurs fois remplacera les gestionnaires que vous fournissez, en écrasant à la fois les gestionnaires par défaut et ceux définis précédemment pour ces événements spécifiques. Les gestionnaires non définis conservent leur comportement par défaut. `setEventHandlers` retourne une fonction de désinscription, et `view.dismiss()` supprime tous les gestionnaires. ::: ```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() { /***/ }, }); ```
Exemples d'événements (cliquez pour développer) Les exemples ci-dessous montrent les propriétés disponibles dans chaque gestionnaire, avec des valeurs illustratives en commentaires. ```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' ```
Vous pouvez enregistrer uniquement les gestionnaires d'événements dont vous avez besoin, et ignorer les autres. Dans ce cas, les écouteurs d'événements inutilisés ne seront pas créés. Aucun gestionnaire d'événements n'est obligatoire. Les gestionnaires d'événements retournent un booléen. Si `true` est retourné, le processus d'affichage est considéré comme terminé : l'écran du flow se ferme et les écouteurs d'événements de cette vue sont supprimés. Certains gestionnaires d'événements ont un comportement par défaut que vous pouvez remplacer si nécessaire : - `onCloseButtonPress` : ferme le flow lorsque le bouton de fermeture est appuyé. - `onUrlPress` : ouvre l'URL dans le navigateur natif via `adapty.openWebUrl`, en respectant l'option **Open in** définie dans le builder, et maintient le flow ouvert. - `onAndroidSystemBack` : maintient le flow ouvert lorsque le bouton **Retour** est appuyé. Retournez `true` pour le fermer. - `onPurchaseCompleted` : maintient le flow ouvert après la fin d'un achat. Retournez `true` pour le fermer. - `onRestoreCompleted` : maintient le flow ouvert après une restauration réussie. Retournez `true` pour le fermer. - `onError` : ferme le flow si son rendu échoue. ### Gestionnaires d'événements \{#event-handlers\} | Gestionnaire d'événement | Description | |:-----------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | Déclenché lorsqu'un utilisateur effectue une action personnalisée, par exemple en cliquant sur un [bouton personnalisé](paywall-buttons). | | **onUrlPress** | Déclenché lorsqu'un utilisateur clique sur une URL dans votre flow. | | **onAndroidSystemBack** | Déclenché lorsqu'un utilisateur appuie sur le bouton système **Retour** d'Android. Le flow reste ouvert par défaut ; retournez `true` pour le fermer. | | **onCloseButtonPress** | Déclenché lorsque le bouton de fermeture est visible et qu'un utilisateur appuie dessus. Il est recommandé de fermer l'écran du flow dans ce gestionnaire. | | **onPurchaseCompleted** | Déclenché lorsque l'achat se termine, qu'il soit réussi, annulé par l'utilisateur ou en attente d'approbation. En cas d'achat réussi, fournit un `AdaptyProfile` mis à jour. Les annulations par l'utilisateur et les paiements en attente (ex. : approbation parentale requise) déclenchent cet événement, pas `onPurchaseFailed`. | | **onPurchaseStarted** | Déclenché lorsqu'un utilisateur appuie sur le bouton d'action "Acheter" pour lancer le processus d'achat. | | **onPurchaseFailed** | Déclenché lorsqu'un achat échoue en raison d'erreurs (ex. : restrictions de paiement, produits invalides, pannes réseau, échecs de vérification des transactions). Non déclenché pour les annulations par l'utilisateur ou les paiements en attente, qui déclenchent `onPurchaseCompleted` à la place. | | **onRestoreStarted** | Déclenché lorsqu'un utilisateur lance un processus de restauration d'achat. | | **onRestoreCompleted** | Déclenché lorsque la restauration des achats réussit et fournit un `AdaptyProfile` mis à jour. Il est recommandé de fermer l'écran si l'utilisateur possède le `accessLevel` requis. Consultez la rubrique [Statut de l'abonnement](capacitor-listen-subscription-changes) pour savoir comment le vérifier. | | **onRestoreFailed** | Déclenché lorsque le processus de restauration échoue et fournit une `AdaptyError`. | | **onProductSelected** | Déclenché lorsqu'un produit dans la vue du flow est sélectionné, vous permettant de surveiller ce que l'utilisateur sélectionne avant l'achat. | | **onError** | Déclenché lorsqu'une erreur survient pendant le rendu de la vue et fournit une `AdaptyError`. Ces erreurs ne devraient pas se produire ; si vous en rencontrez une, merci de nous le signaler. | | **onLoadingProductsFailed** | Déclenché lorsque le chargement des produits échoue et fournit une `AdaptyError`. Si vous n'avez pas défini `prefetchProducts: true` lors de la création de la vue, AdaptyUI récupérera les objets nécessaires depuis le serveur par lui-même. | | **onAppeared** | Déclenché lorsque le flow est affiché à l'utilisateur. Sur iOS, également déclenché lorsqu'un utilisateur appuie sur le [bouton de paywall web](web-paywall#step-2a-add-a-web-purchase-button) dans un flow, et qu'un paywall web s'ouvre dans un navigateur intégré. | | **onDisappeared** | Déclenché lorsque le flow est fermé par l'utilisateur. Sur iOS, également déclenché lorsqu'un [paywall web](web-paywall#step-2a-add-a-web-purchase-button) ouvert depuis un flow dans un navigateur intégré disparaît de l'écran. | | **onWebPaymentNavigationFinished** | Déclenché après une tentative d'ouverture d'un [paywall web](web-paywall) pour un achat, qu'elle ait réussi ou échoué. | | **onRequestAppReview** | Réservé aux demandes d'évaluation de l'application depuis un flow. Les flows ne déclenchent pas encore de demandes d'évaluation, vous n'avez donc pas besoin de l'implémenter. | | **onAnalytics** | Réservé aux événements analytiques personnalisés depuis un flow. Les flows n'émettent pas encore ces événements vers votre code, vous n'avez donc pas besoin de l'implémenter. | | **onRequestPermission** | Réservé aux demandes d'autorisation système (comme les notifications push ou l'accès à la caméra) depuis un flow. Les flows ne déclenchent pas encore de demandes d'autorisation, vous n'avez donc pas besoin de l'implémenter. | | **onObserverPurchaseInitiated** | Mode observateur uniquement : déclenché lorsqu'un utilisateur appuie sur le bouton d'achat dans un flow. Adapty n'effectue pas l'achat — réalisez-le avec votre propre code d'achat, puis signalez la transaction à Adapty. Voir [Gérer les achats en mode observateur](#handle-purchases-in-observer-mode) ci-dessous. | | **onObserverRestoreInitiated** | Mode observateur uniquement : déclenché lorsqu'un utilisateur appuie sur le bouton de restauration dans un flow. Adapty n'effectue pas la restauration — faites-le vous-même, puis signalez les transactions restaurées. Voir [Gérer les achats en mode observateur](#handle-purchases-in-observer-mode) ci-dessous. | ### Gérer les achats en mode observateur \{#handle-purchases-in-observer-mode\} Si vous avez activé le SDK en [mode observateur](implement-observer-mode-capacitor) (`observerMode: true`) et que vous affichez un flow rendu par Adapty, le SDK n'effectue pas les achats pour vous. Lorsqu'un utilisateur appuie sur le bouton d'achat ou de restauration, le SDK déclenche `onObserverPurchaseInitiated` ou `onObserverRestoreInitiated` à la place, afin que vous puissiez effectuer l'achat ou la restauration avec votre propre code. Consultez [Afficher les flows en mode observateur](capacitor-present-flows-in-observer-mode) pour la configuration complète.
:::important Ce guide couvre la gestion des événements pour les achats, les restaurations, la sélection de produits et le rendu des paywalls. Vous devez également implémenter la gestion des boutons (fermeture du paywall, ouverture de liens, etc.). Consultez notre [guide sur la gestion des actions de boutons](capacitor-handle-paywall-actions) pour plus de détails. ::: Les paywalls configurés avec le [Paywall Builder](adapty-paywall-builder) n'ont pas besoin de code supplémentaire pour effectuer et restaurer des achats. Ils génèrent cependant des événements auxquels votre application peut réagir. Ces événements incluent des appuis sur des boutons (boutons de fermeture, URLs, sélections de produits, etc.) ainsi que des notifications sur les actions liées aux achats effectuées sur le paywall. Découvrez comment répondre à ces événements ci-dessous. Pour contrôler ou surveiller les processus qui se déroulent sur l'écran du paywall dans votre application mobile, implémentez la méthode `view.setEventHandlers` : ```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 }, }); ```
Exemples d'événements (cliquez pour développer) ```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" } } } ```
Vous pouvez enregistrer uniquement les gestionnaires d'événements dont vous avez besoin, et ignorer les autres. Dans ce cas, les écouteurs d'événements inutilisés ne seront pas créés. Aucun gestionnaire d'événements n'est obligatoire. Les gestionnaires d'événements retournent un booléen. Si `true` est retourné, le processus d'affichage est considéré comme terminé : l'écran du paywall se ferme et les écouteurs d'événements de cette vue sont supprimés. Certains gestionnaires d'événements ont un comportement par défaut que vous pouvez remplacer si nécessaire : - `onCloseButtonPress` : ferme le paywall lorsque le bouton de fermeture est appuyé. - `onAndroidSystemBack` : ferme le paywall lorsque le bouton **Retour** est appuyé. - `onRestoreCompleted` : ferme le paywall après une restauration réussie. - `onPurchaseCompleted` : ferme le paywall sauf si l'utilisateur a annulé. - `onRenderingFailed` : ferme le paywall si son rendu échoue. - `onUrlPress` : ouvre les URLs dans le navigateur système et maintient le paywall ouvert. ### Gestionnaires d'événements \{#event-handlers\} | Gestionnaire d'événement | Description | |:----------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | Déclenché lorsqu'un utilisateur effectue une action personnalisée, par exemple en cliquant sur un [bouton personnalisé](paywall-buttons). | | **onUrlPress** | Déclenché lorsqu'un utilisateur clique sur une URL dans votre paywall. | | **onAndroidSystemBack** | Déclenché lorsqu'un utilisateur appuie sur le bouton système **Retour** d'Android. | | **onCloseButtonPress** | Déclenché lorsque le bouton de fermeture est visible et qu'un utilisateur appuie dessus. Il est recommandé de fermer l'écran du paywall dans ce gestionnaire. | | **onPurchaseCompleted** | Déclenché lorsque l'achat se termine, qu'il soit réussi, annulé par l'utilisateur ou en attente d'approbation. En cas d'achat réussi, fournit un `AdaptyProfile` mis à jour. Les annulations par l'utilisateur et les paiements en attente (ex. : approbation parentale requise) déclenchent cet événement, pas `onPurchaseFailed`. | | **onPurchaseStarted** | Déclenché lorsqu'un utilisateur appuie sur le bouton d'action "Acheter" pour lancer le processus d'achat. | | **onPurchaseCancelled** | Déclenché lorsqu'un utilisateur lance le processus d'achat et l'interrompt manuellement (annule la boîte de dialogue de paiement). | | **onPurchaseFailed** | Déclenché lorsqu'un achat échoue en raison d'erreurs (ex. : restrictions de paiement, produits invalides, pannes réseau, échecs de vérification des transactions). Non déclenché pour les annulations par l'utilisateur ou les paiements en attente, qui déclenchent `onPurchaseCompleted` à la place. | | **onRestoreStarted** | Déclenché lorsqu'un utilisateur lance un processus de restauration d'achat. | | **onRestoreCompleted** | Déclenché lorsque la restauration des achats réussit et fournit un `AdaptyProfile` mis à jour. Il est recommandé de fermer l'écran si l'utilisateur possède le `accessLevel` requis. Consultez la rubrique [Statut de l'abonnement](capacitor-listen-subscription-changes) pour savoir comment le vérifier. | | **onRestoreFailed** | Déclenché lorsque le processus de restauration échoue et fournit une `AdaptyError`. | | **onProductSelected** | Déclenché lorsqu'un produit dans la vue du paywall est sélectionné, vous permettant de surveiller ce que l'utilisateur sélectionne avant l'achat. | | **onAppeared** | Déclenché lorsque la vue du paywall apparaît à l'écran. Sur iOS, également déclenché lorsqu'un utilisateur appuie sur le [bouton de paywall web](web-paywall#step-2a-add-a-web-purchase-button) dans un paywall, et qu'un paywall web s'ouvre dans un navigateur intégré. | | **onDisappeared** | Déclenché lorsque la vue du paywall disparaît de l'écran. Sur iOS, également déclenché lorsqu'un [paywall web](web-paywall#step-2a-add-a-web-purchase-button) ouvert depuis un paywall dans un navigateur intégré disparaît de l'écran. | | **onRenderingFailed** | Déclenché lorsqu'une erreur survient pendant le rendu de la vue et fournit une `AdaptyError`. Ces erreurs ne devraient pas se produire ; si vous en rencontrez une, merci de nous le signaler. | | **onLoadingProductsFailed** | Déclenché lorsque le chargement des produits échoue et fournit une `AdaptyError`. Si vous n'avez pas défini `prefetchProducts: true` lors de la création de la vue, AdaptyUI récupérera les objets nécessaires depuis le serveur par lui-même. |
--- # File: capacitor-use-fallback-paywalls --- --- title: "Capacitor - Use fallback paywalls" description: "Handle cases when users are offline or Adapty servers aren't available" --- To maintain a fluid user experience, it is important to set up [fallbacks](/fallback-paywalls) for your flows, [paywalls](paywalls), and [onboardings](onboardings). This precaution extends the application's capabilities in case of partial or complete loss of internet connection. * **If the application cannot access Adapty servers:** It will be able to display a fallback flow or paywall, and access the local onboarding configuration. * **If the application cannot access the internet:** It will be able to display a fallback flow or paywall. Onboardings include remote content and require an internet connection to function. :::important Before you follow the steps in this guide, [download](/local-fallback-paywalls) the fallback configuration files from Adapty. ::: ## Configuration \{#configuration\} ### Android \{#android\} 1. Ajoutez le fichier de configuration de secours à votre application. Sélectionnez l'un des répertoires suivants : * **android/app/src/main/assets/** * **android/app/src/main/res/raw/** Remarque : le dossier `res/raw` suit une convention de nommage particulière (commencer par une lettre, pas de majuscules, pas de caractères spéciaux sauf le tiret bas, et pas d'espaces dans les noms). 2. Mettez à jour la propriété `android` de la constante `FileLocation` : * Si le fichier se trouve dans le répertoire `assets`, passez le chemin du fichier relatif à ce répertoire. * Si le fichier se trouve dans le répertoire `res/raw`, passez le nom du fichier sans l'extension. ### iOS \{#ios\} 1. Ajoutez le fichier JSON de secours à votre bundle de projet : ouvrez le menu **File** dans XCode et sélectionnez l'option **Add Files to "YourProjectName"**. 2. Passez le nom de votre fichier de configuration à la propriété `ios` de la constante `FileLocation`. ## Exemple \{#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` doit être exécuté avant que le SDK ne récupère le flow, le paywall ou l'onboarding cible. ::: Paramètres : | Paramètre | Description | | :------------------- | :------------------------------------------------------- | | **fileLocation** | Objet représentant l'emplacement du fichier de configuration de secours. | --- # File: capacitor-localizations-and-locale-codes --- --- title: "Utiliser les localisations et les codes de langue dans le SDK Capacitor" description: "Apprenez à localiser les paywalls dans votre application Capacitor avec le SDK Adapty." --- ## Pourquoi c'est important \{#why-this-is-important\} Les codes de langue entrent en jeu lorsqu'Adapty choisit la localisation pour un flow et lorsque vous lisez un Remote Config pour un paywall personnalisé. Les codes de langue sont complexes et peuvent varier d'une plateforme à l'autre. Adapty s'appuie donc sur un standard interne unique pour toutes les plateformes qu'il prend en charge. Comprendre ce standard vous aide à anticiper quelle localisation reçoit un utilisateur. ## Standard des codes de langue chez Adapty \{#locale-code-standard-at-adapty\} Pour les codes de langue, Adapty utilise une version légèrement modifiée du [standard BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) : chaque code est composé de sous-balises en minuscules, séparées par des tirets. Quelques exemples : `en` (anglais), `pt-br` (portugais (Brésil)), `zh` (chinois simplifié), `zh-hant` (chinois traditionnel). ## Correspondance des codes de langue \{#locale-code-matching\} Lorsqu'Adapty recherche la localisation qui correspond à la locale d'un utilisateur, voici ce qui se passe : 1. La chaîne de locale est convertie en minuscules et tous les underscores (`_`) sont remplacés par des tirets (`-`) 2. Adapty recherche la localisation dont le code de locale correspond exactement 3. Si aucune correspondance n'est trouvée, Adapty extrait la sous-chaîne avant le premier tiret (`pt` pour `pt-br`) et recherche la localisation correspondante 4. Si aucune correspondance n'est encore trouvée, Adapty renvoie le contenu dans la locale par défaut du flow Cette approche permet à `'pt_BR'`, `pt-BR` et `pt-br` de tous correspondre à la même localisation. ## Implémentation des localisations \{#implementing-localizations\} Dans le SDK v4, vous ne transmettez pas de code de langue lorsque vous récupérez un flow — `getFlow` renvoie le flow avec toutes ses localisations, et Adapty en applique une au moment où la vue du flow est construite. - **Flows construits dans le builder** : le SDK ne lit pas la langue de l'appareil, donc déterminez-la dans votre application et transmettez-la comme option `locale` de `createFlowView`. C'est facultatif — omettez-la et le flow s'affiche en `en`, ou dans sa [langue par défaut](add-paywall-locale-in-adapty-paywall-builder#set-the-default-locale) si le flow ne possède pas de localisation `en`. Si vous demandez une localisation que le flow n'a pas, la vue revient à la langue par défaut du flow sans erreur, et les chaînes manquantes dans la localisation choisie sont récupérées depuis celle par défaut. ```typescript showLineNumbers import { createFlowView } from '@adapty/capacitor'; const view = await createFlowView(flow, { locale: 'es' }); ``` `view.locale` indique la localisation avec laquelle la vue a été construite. L'option `locale` et `view.locale` nécessitent le SDK Capacitor 4.0.1-beta.1 ; `view.locale` est `undefined` sur les versions antérieures. - **Paywalls personnalisés (Remote Config)** : `getFlow` retourne toutes les localisations configurées dans `flow.remoteConfigs`. Chaque entrée possède un code `lang` et un objet `data`. Sélectionnez l'entrée correspondant à l'utilisateur, avec votre propre fallback : ```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 ``` Les règles de correspondance des codes de langue décrites ci-dessus expliquent comment Adapty normalise les codes `lang` stockés dans chaque Remote Config. ## Pourquoi c'est important \{#why-this-is-important\} Il existe quelques scénarios où les codes de locale entrent en jeu — par exemple, lorsque vous essayez de récupérer le bon paywall pour la localisation actuelle de votre application. Les codes de locale étant complexes et pouvant varier d'une plateforme à l'autre, nous nous appuyons sur un standard interne pour toutes les plateformes que nous supportons. Cependant, en raison de cette complexité, il est vraiment important que vous compreniez exactement ce que vous envoyez à notre serveur pour obtenir la bonne localisation, et ce qui se passe ensuite — afin que vous receviez toujours ce que vous attendez. ## Standard des codes de langue chez Adapty \{#locale-code-standard-at-adapty\} Pour les codes de langue, Adapty utilise une version légèrement modifiée du [standard BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) : chaque code est composé de sous-tags en minuscules, séparés par des tirets. Quelques exemples : `en` (anglais), `pt-br` (portugais (Brésil)), `zh` (chinois simplifié), `zh-hant` (chinois traditionnel). ## Correspondance des codes de langue \{#locale-code-matching\} Lorsqu'Adapty reçoit un appel du SDK client avec un code de langue et commence à chercher la localisation correspondante d'un paywall, voici ce qui se passe : 1. La chaîne de locale reçue est convertie en minuscules et tous les underscores (`_`) sont remplacés par des tirets (`-`) 2. On recherche ensuite la localisation dont le code de locale correspond exactement 3. Si aucune correspondance n'est trouvée, on extrait la sous-chaîne avant le premier tiret (`pt` pour `pt-br`) et on cherche la localisation correspondante 4. Si aucune correspondance n'est trouvée non plus, on renvoie le contenu dans la locale par défaut du paywall De cette façon, un appareil iOS qui a envoyé `'pt_BR'`, un appareil Android qui a envoyé `pt-BR`, et un autre appareil qui a envoyé `pt-br` obtiendront le même résultat. ## Implémentation des localisations : méthode recommandée \{#implementing-localizations-recommended-way\} Si vous vous interrogez sur les localisations, il y a de grandes chances que vous gériez déjà des fichiers de chaînes localisées dans votre projet. Dans ce cas, nous vous recommandons d'ajouter une paire clé-valeur avec le code de locale Adapty correspondant dans chacun de vos fichiers de localisation. Récupérez ensuite la valeur de cette clé lors de l'appel au SDK, comme ceci : ```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); }; }; ``` De cette façon, vous êtes totalement maître de la localisation qui sera récupérée pour chaque utilisateur de votre application. ## Implémenter les localisations : une autre approche \{#implementing-localizations-the-other-way\} Vous pouvez obtenir des résultats similaires (mais non identiques) sans définir explicitement de codes de langue pour chaque localisation. Il s'agit d'extraire un code de langue depuis d'autres objets fournis par votre plateforme, comme ceci : ```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); }; ``` Notez que nous déconseillons cette approche pour plusieurs raisons : 1. Sur iOS, les langues préférées et la locale actuelle ne sont pas identiques. Si vous voulez que la localisation soit sélectionnée correctement, vous devrez soit vous reposer sur la logique d'Apple, qui fonctionne directement si vous utilisez l'approche recommandée avec des fichiers de chaînes localisées, soit la recréer vous-même. 2. Il est difficile de prédire ce que le serveur d'Adapty recevra exactement. Par exemple, sur iOS, il est possible d'obtenir une locale comme `ar_OM@numbers='latn'` sur un appareil et de l'envoyer à notre serveur. Pour cet appel, vous obtiendrez non pas la localisation `ar-om` que vous cherchiez, mais `ar`, ce qui est probablement inattendu. Should you decide to use this approach anyway — make sure you've covered all the relevant use cases. --- # File: capacitor-web-paywall --- --- title: "Implémenter les paywalls web" description: "Apprenez à implémenter les paywalls web dans votre application Capacitor avec le SDK Adapty." --- :::important Avant de commencer, assurez-vous d'avoir [configuré votre paywall web dans le tableau de bord](web-paywall) et d'avoir installé la version 3.6.1 ou ultérieure du SDK Adapty. ::: ## Ouvrir les paywalls web \{#open-web-paywalls\} Si vous travaillez avec un paywall que vous avez développé vous-même, vous devez gérer les paywalls web via la méthode du SDK. La méthode `.openWebPaywall` : 1. Génère une URL unique permettant à Adapty d'associer un paywall spécifique affiché à un utilisateur particulier à la page web vers laquelle il est redirigé. 2. Détecte quand vos utilisateurs reviennent dans l'application, puis appelle `.getProfile` à intervalles courts pour déterminer si les droits d'accès du profil ont été mis à jour. Ainsi, si le paiement a réussi et que les droits d'accès ont été mis à jour, l'abonnement s'active dans l'application presque immédiatement. ```typescript showLineNumbers try { await adapty.openWebPaywall({ paywallOrProduct: product }); } catch (error) { console.error('Failed to open web paywall:', error); } ``` :::note Il existe deux versions de la méthode `openWebPaywall` : 1. `openWebPaywall({ paywallOrProduct: product })` qui génère des URLs par paywall et ajoute également les données du produit aux URLs. 2. `openWebPaywall({ paywallOrProduct: paywall })` qui génère des URLs par paywall sans ajouter les données du produit aux URLs. Utilisez-la quand vos produits dans le paywall Adapty diffèrent de ceux du paywall web. Dans le SDK v4, le côté paywall de `paywallOrProduct` prend un `AdaptyFlowPaywall` — une variante paywall du flow récupéré. Vérifiez que `flow.paywalls` n'est pas vide avant d'y accéder par index, par exemple `flow.paywalls[0]`. ::: #### Gérer les erreurs \{#handle-errors\} | Erreur | Description | Action recommandée | |-----------------------------------------|---------------------------------------------------------------------|----------------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | Le paywall n'a pas d'URL d'achat web configurée | Vérifiez que le paywall a été correctement configuré dans l'Adapty Dashboard | | AdaptyError.productWithoutPurchaseUrl | Le produit n'a pas d'URL d'achat web | Vérifiez la configuration du produit dans l'Adapty Dashboard | | AdaptyError.failedOpeningWebPaywallUrl | Impossible d'ouvrir l'URL dans le navigateur | Vérifiez les paramètres de l'appareil ou proposez une autre méthode d'achat | | AdaptyError.failedDecodingWebPaywallUrl | Impossible d'encoder correctement les paramètres dans l'URL | Vérifiez que les paramètres d'URL sont valides et correctement formatés | ## Obtenir l'URL du paywall web sans l'ouvrir \{#get-the-web-paywall-url-without-opening-it\} Si vous souhaitez afficher vous-même la page d'achat web plutôt que de laisser le SDK l'ouvrir, utilisez `createWebPaywallUrl`. Elle retourne la même URL unique que celle qu'`openWebPaywall` ouvrirait, vous permettant ainsi de l'afficher dans votre propre vue web ou de gérer la redirection à votre façon. Elle accepte le même argument `paywallOrProduct` — une variante paywall du flow récupéré (`AdaptyFlowPaywall`) ou un `AdaptyPaywallProduct`. ```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 Pour ouvrir une URL arbitraire (pas un paywall web) dans le navigateur natif — par exemple, depuis le bouton d'un flow — utilisez plutôt [`adapty.openWebUrl`](capacitor-handle-paywall-actions#open-urls-from-flows-and-paywalls). ::: ## Ouvrir les paywalls web dans un navigateur intégré \{#open-web-paywalls-in-an-in-app-browser\} :::important L'ouverture des paywalls web dans un navigateur intégré est prise en charge à partir du SDK Adapty v3.15. ::: Par défaut, les paywalls web s'ouvrent dans le navigateur externe. Pour offrir une expérience utilisateur fluide, vous pouvez ouvrir les paywalls web dans un navigateur intégré. Cela affiche la page d'achat web directement dans votre application, permettant aux utilisateurs de finaliser leurs transactions sans changer d'application. Pour activer cette option, définissez `openIn` sur `WebPresentation.BrowserInApp` dans `openWebPaywall` : ```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: "Afficher les flows en mode Observer dans le SDK Capacitor" description: "Affichez les flows et les paywalls Paywall Builder en mode Observer dans votre application Capacitor tout en gérant les achats avec votre propre code." --- Si vous avez personnalisé un flow ou un paywall avec le builder, vous n'avez pas à vous soucier de son rendu dans le code de votre application mobile pour l'afficher à l'utilisateur. Un tel flow ou paywall contient à la fois ce qui doit être affiché et comment l'afficher. :::warning Cette section concerne uniquement le [mode Observer](observer-vs-full-mode). Si vous ne travaillez pas en mode Observer, consultez la rubrique [Afficher les flows et paywalls](capacitor-present-paywalls). ::: :::info Cette fonctionnalité nécessite Adapty Capacitor SDK 4.0 ou une version ultérieure — elle n'était auparavant disponible que dans les SDK iOS et Android natifs. Consultez le [guide de migration](migration-to-capacitor-sdk-v4) pour effectuer la mise à niveau. :::
Avant de commencer à afficher des flows (Cliquer pour développer) 1. Configurez l'intégration initiale d'Adapty [avec l'App Store](initial_ios) et [avec Google Play](initial-android). 2. Installez et configurez le SDK Adapty. Assurez-vous de définir le paramètre `observerMode` sur `true`. Consultez le [guide d'installation du SDK Capacitor](sdk-installation-capacitor#activate-adapty-module-of-adapty-sdk). 3. [Créez des produits](create-product) dans l'Adapty Dashboard. 4. [Configurez les flows ou paywalls dans les builders](create-paywall) et assignez-leur des produits. 5. [Créez des placements et assignez-leur vos flows ou paywalls](create-placement). 6. [Récupérez les flows et leur configuration](capacitor-get-pb-paywalls) dans le code de votre application mobile.
En mode Observer, le SDK n'effectue pas les achats à votre place. Lorsqu'un utilisateur appuie sur le bouton d'achat ou de restauration dans un flow ou paywall rendu par Adapty, le SDK invoque votre gestionnaire d'événements `onObserverPurchaseInitiated` ou `onObserverRestoreInitiated` — effectuez l'achat ou la restauration avec votre propre code à cet endroit. 1. Définissez les gestionnaires d'événements du mode Observer sur la vue. Contrairement à d'autres plateformes, il n'existe pas d'objet resolver séparé — les gestionnaires font partie des [gestionnaires d'événements](capacitor-handling-events) habituels, définissez-les donc sur chaque vue que vous créez : ```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; }, }); ``` Le gestionnaire `onObserverPurchaseInitiated` vous informe que l'utilisateur a initié un achat, et `onObserverRestoreInitiated` — que l'utilisateur a initié une restauration. Déclenchez votre flow d'achat ou de restauration personnalisé en réponse. Pensez également à invoquer les callbacks suivants pour notifier AdaptyUI de l'avancement de l'achat ou de la restauration. C'est nécessaire pour un comportement correct du flow, notamment l'affichage du loader : | Callback | Description | | :----------------- | :----------------------------------------------------------------------------------------------- | | onStartPurchase() | Ce callback doit être invoqué pour notifier AdaptyUI que l'achat a commencé. | | onFinishPurchase() | Ce callback doit être invoqué pour notifier AdaptyUI que l'achat est terminé. | | onStartRestore() | Ce callback doit être invoqué pour notifier AdaptyUI que la restauration a commencé. | | onFinishRestore() | Ce callback doit être invoqué pour notifier AdaptyUI que la restauration est terminée. | 2. Affichez la vue du flow comme d'habitude : [récupérez le flow et créez sa vue](capacitor-get-pb-paywalls), puis [affichez-la](capacitor-present-paywalls). Aucun paramètre supplémentaire n'est nécessaire — les gestionnaires se déclenchent uniquement lorsque le SDK a été activé avec `observerMode: true`. :::warning N'oubliez pas de [signaler la transaction et de l'associer au paywall](report-transactions-observer-mode-capacitor). Sans cela, Adapty ne reconnaîtra pas la transaction et ne pourra pas identifier le paywall source de l'achat. ::: --- # File: capacitor-implement-paywalls-manually --- --- title: "Implémenter les paywalls manuellement" description: "Découvrez comment implémenter les paywalls manuellement dans votre application Capacitor avec le SDK Adapty." --- ## Accepter les achats \{#accept-purchases\} Si vous travaillez avec des paywalls que vous avez implémentés vous-même, vous pouvez déléguer la gestion des achats à Adapty en utilisant la méthode `makePurchase`. De cette façon, nous gérons tous les scénarios utilisateur et vous n'avez qu'à traiter les résultats des achats. :::important `makePurchase` fonctionne avec les produits créés dans l'Adapty Dashboard. Assurez-vous de configurer les produits et les moyens de les récupérer dans le tableau de bord en suivant le [guide de démarrage rapide](quickstart). ::: ## Mode observateur \{#observer-mode\} Si vous souhaitez implémenter votre propre logique de gestion des achats de A à Z tout en bénéficiant des analyses avancées d'Adapty, vous pouvez utiliser le mode observateur. :::important Consultez les limitations du mode observateur [ici](observer-vs-full-mode). ::: --- # File: capacitor-quickstart-manual --- --- title: "Activer les achats dans votre paywall personnalisé avec le SDK Capacitor" description: "Intégrez le SDK Adapty dans vos paywalls Capacitor personnalisés pour activer les achats intégrés." --- Ce guide explique comment intégrer Adapty dans vos paywalls personnalisés. Gardez le contrôle total sur l'implémentation du paywall, tandis que le SDK Adapty récupère les produits, gère les nouveaux achats et restaure les achats précédents. Ce guide utilise les APIs du SDK Adapty Capacitor v4 — si vous êtes sur la v3, consultez le [guide de migration](migration-to-capacitor-sdk-v4) pour les noms de méthodes correspondants. :::important **Ce guide s'adresse aux développeurs qui implémentent des paywalls personnalisés.** Si vous souhaitez la solution la plus simple pour activer les achats, utilisez le [Adapty Paywall Builder](capacitor-quickstart-paywalls). Avec le Paywall Builder, vous créez des paywalls dans un éditeur visuel sans code, Adapty gère automatiquement toute la logique d'achat, et vous pouvez tester différents designs sans republier votre application. ::: ## Avant de commencer \{#before-you-start\} ### Configurer les produits \{#set-up-products\} Pour activer les achats intégrés, vous devez comprendre trois concepts clés : - [**Produits**](product) – tout ce que les utilisateurs peuvent acheter (abonnements, consommables, accès à vie) - [**Paywalls**](paywalls) – des configurations qui définissent quels produits proposer. Dans Adapty, les paywalls sont le seul moyen de récupérer des produits, mais cette conception vous permet de modifier les produits, les prix et les offres sans toucher au code de votre application. Dans le SDK v4, les variations de paywall pour un placement sont portées par un objet **flow** — vous récupérez un flow et interrogez ses produits. - [**Placements**](placements) – où et quand vous affichez les paywalls dans votre application (comme `main`, `onboarding`, `settings`). Vous configurez les paywalls pour les placements dans le tableau de bord, puis vous les demandez par ID de placement dans votre code. Cela facilite les tests A/B et l'affichage de paywalls différents à différents utilisateurs. Assurez-vous de bien comprendre ces concepts même si vous travaillez avec votre paywall personnalisé. En gros, ce sont simplement votre façon de gérer les produits que vous vendez dans votre application. Pour implémenter votre paywall personnalisé, vous devrez créer un **paywall** et l'ajouter à un **placement**. Cette configuration vous permet de récupérer vos produits. Pour comprendre ce que vous devez faire dans le tableau de bord, suivez le guide de démarrage rapide [ici](quickstart). ### Gérer les utilisateurs \{#manage-users\} Vous pouvez travailler avec ou sans authentification backend de votre côté. Cependant, le SDK Adapty gère différemment les utilisateurs anonymes et identifiés. Lisez le [guide de démarrage rapide sur l'identification](capacitor-quickstart-identify) pour comprendre les spécificités et vous assurer de travailler correctement avec les utilisateurs. ## Étape 1. Récupérer les produits \{#step-1-get-products\} Pour récupérer les produits pour votre paywall personnalisé, vous devez : 1. Obtenir l'objet `flow` en passant l'ID du [placement](placements) à la méthode `getFlow`. 2. Obtenir le tableau de produits pour ce flow en utilisant la méthode `getPaywallProducts`. ```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 } } ``` ## Étape 2. Accepter les achats \{#step-2-accept-purchases\} Quand un utilisateur appuie sur un produit dans votre paywall personnalisé, appelez la méthode `makePurchase` avec le produit sélectionné. Cela gérera le processus d'achat et retournera le profil mis à jour. ```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 } } ``` ## Étape 3. Restaurer les achats \{#step-3-restore-purchases\} Les stores d'applications exigent que toutes les applications avec des abonnements fournissent un moyen pour les utilisateurs de restaurer leurs achats. Appelez la méthode `restorePurchases` quand l'utilisateur appuie sur le bouton de restauration. Cela synchronisera son historique d'achats avec Adapty et retournera le profil mis à jour. ```typescript showLineNumbers async function restorePurchases() { try { const profile: AdaptyProfile = await adapty.restorePurchases(); // Restore successful, profile updated } catch (error) { // Handle the error } } ``` ## Étape 4. Vérifier le statut de l'abonnement \{#step-4-check-the-subscription-status\} Après un achat ou une restauration, vérifiez le [niveau d'accès](access-level) de l'utilisateur pour décider d'afficher le paywall ou de déverrouiller les fonctionnalités payantes. Les méthodes `makePurchase` et `restorePurchases` retournent déjà le profil mis à jour ; chaque fois que vous avez besoin du statut actuel ailleurs dans l'application, utilisez la méthode `getProfile` : ```typescript showLineNumbers async function hasPremiumAccess(): Promise { try { const profile = await adapty.getProfile(); return profile.accessLevels?.['premium']?.isActive ?? false; } catch (error) { // Handle the error } return false; } ``` Pour d'autres façons de vérifier et surveiller le statut de l'abonnement, y compris l'écoute des mises à jour en temps réel, consultez [Vérifier le statut de l'abonnement](capacitor-check-subscription-status). ## Prochaines étapes \{#next-steps\} :::tip Des questions ou des problèmes ? Consultez notre [forum d'assistance](https://adapty.featurebase.app/) où vous trouverez des réponses aux questions fréquentes ou pourrez poser les vôtres. Notre équipe et notre communauté sont là pour vous aider ! ::: Votre paywall est prêt à être affiché dans l'application. Testez vos achats dans le [sandbox App Store](test-purchases-in-sandbox) ou dans le [Google Play Store](testing-on-android) pour vous assurer de pouvoir effectuer un achat test depuis le paywall. Pour voir comment cela fonctionne dans une implémentation prête pour la production, consultez le fichier [App.tsx](https://github.com/adaptyteam/AdaptySDK-Capacitor/blob/master/examples/adapty-devtools/src/screens/app/App.tsx) dans notre application exemple, qui illustre la gestion des achats avec une gestion des erreurs appropriée, des états de chargement et une intégration complète du SDK. --- # File: fetch-paywalls-and-products-capacitor --- --- title: "Récupérer les paywalls et produits pour les paywalls Remote Config dans le SDK Capacitor" description: "Récupérez les paywalls et produits dans le SDK Adapty Capacitor pour améliorer la monétisation des utilisateurs." --- Avant de présenter le Remote Config et les paywalls personnalisés, vous devez récupérer les informations les concernant. Notez que cette rubrique traite du Remote Config et des paywalls personnalisés. Pour récupérer des flows ou des paywalls personnalisés dans le **Flow Builder** ou le **Paywall Builder**, consultez [Récupérer les flows du Flow Builder et les paywalls du Paywall Builder ainsi que leur configuration](capacitor-get-pb-paywalls). :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base. :::
Avant de commencer à récupérer les flows et les produits dans votre application mobile (cliquez pour développer) 1. [Créez vos produits](create-product) dans l'Adapty Dashboard. 2. [Créez un flow ou un paywall et intégrez les produits](create-paywall) dans l'Adapty Dashboard. 3. [Créez des placements et intégrez votre flow ou paywall dans le placement](create-placement) dans l'Adapty Dashboard. 4. [Installez le SDK Adapty](sdk-installation-capacitor) dans votre application mobile.
## Récupérer les informations d'un flow \{#fetch-flow-information\} Dans Adapty, un [produit](product) regroupe des produits issus de l'App Store et de Google Play. Ces produits multi-plateformes sont intégrés dans des flows et des paywalls, ce qui vous permet de les présenter dans des placements spécifiques de votre application mobile. Pour afficher les produits, vous devez obtenir un `AdaptyFlow` depuis l'un de vos [placements](placements) via la méthode `getFlow`. :::important **N'écrivez pas les IDs de produits en dur.** Le seul ID que vous devez coder en dur est l'ID de placement. Les flows sont configurés à distance, donc le nombre de produits et les offres disponibles peuvent changer à tout moment. Votre application doit gérer ces changements dynamiquement — si un flow retourne deux produits aujourd'hui et trois demain, affichez-les tous sans modifier le code. ::: ```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); } ``` | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements). C'est la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK tente de charger les données depuis le serveur et renvoie les données en cache en cas d'échec. Nous recommandons cette option, car elle garantit que vos utilisateurs obtiennent toujours les données les plus récentes.

Cependant, si vous pensez que vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour renvoyer les données en cache si elles existent. Dans ce cas, les utilisateurs risquent de ne pas obtenir les toutes dernières données, mais ils bénéficieront de temps de chargement plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sans risque de l'utiliser pendant la session pour éviter les requêtes réseau.

Notez que le cache reste intact au redémarrage de l'application et n'est effacé qu'en cas de réinstallation ou de nettoyage manuel.

Le SDK Adapty stocke les flows et les paywalls sur deux couches : le cache mis à jour régulièrement décrit ci-dessus et les [paywalls de secours](capacitor-use-fallback-paywalls). Nous utilisons également un CDN pour récupérer les flows et les paywalls plus rapidement, ainsi qu'un serveur de secours indépendant en cas d'inaccessibilité du CDN. Ce système est conçu pour garantir que vous obtenez toujours la dernière version de vos flows tout en assurant la fiabilité, même lorsque la connexion internet est limitée.

| | **params.loadTimeoutMs** |

optionnel

par défaut : 5000 ms

|

Cette valeur limite le délai d'attente (en millisecondes) pour cette méthode. Si le délai est dépassé, les données en cache ou le fallback local sont renvoyés.

Notez que dans de rares cas, cette méthode peut expirer légèrement après le délai spécifié dans `loadTimeoutMs`, car l'opération peut reposer sur différentes requêtes en coulisse.

| :::note Dans la v4, `getFlow` ne prend plus de paramètre `locale`. Pour les paywalls personnalisés, toutes les locales disponibles sont renvoyées dans le Remote Config du flow (`flow.remoteConfigs`) — choisissez celle qui correspond à la langue de l'appareil ou aux paramètres de l'application. ::: Ne codez pas en dur les identifiants de produits ! Les flows étant configurés à distance, les produits disponibles, leur nombre et les offres spéciales (comme les essais gratuits) peuvent changer au fil du temps. Assurez-vous que votre code gère ces scénarios. Par exemple, si vous récupérez initialement 2 produits, votre application doit afficher ces 2 produits. Mais si vous en récupérez ensuite 3, votre application doit tous les afficher sans nécessiter de modification du code. La seule chose à coder en dur est l'identifiant du placement. Paramètres de réponse : | Paramètre | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Un objet `AdaptyFlow` contenant le placement, les identifiants (`id`, `variationId`), le nom, ses variantes de paywall (`paywalls`), et un tableau `remoteConfigs` (une entrée par locale configurée). Pour récupérer les produits du flow, appelez `getPaywallProducts({ flow })`. | ## Récupérer les produits \{#fetch-products\} Une fois que vous avez le flow, vous pouvez interroger le tableau de produits qui lui correspond : ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ flow }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` Paramètres de la réponse : | Paramètre | Description | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Liste d'objets [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) avec : identifiant du produit, nom du produit, prix, devise, durée de l'abonnement et plusieurs autres propriétés. | Lors de la mise en œuvre de votre propre design de paywall, vous aurez probablement besoin d'accéder à ces propriétés depuis l'objet [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct). Les propriétés les plus couramment utilisées sont illustrées ci-dessous, mais consultez le document lié pour obtenir tous les détails sur l'ensemble des propriétés disponibles. | Propriété | Description | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Pour afficher le titre du produit, utilisez `product.localizedTitle`. La localisation est basée sur le pays du store sélectionné par l'utilisateur, et non sur la locale de l'appareil. | | **Price** | Pour afficher une version localisée du prix, utilisez `product.price?.localizedString`. Cette localisation est basée sur les informations de locale de l'appareil. Vous pouvez également accéder au prix sous forme de nombre avec `product.price?.amount`. La valeur sera fournie dans la devise locale. Pour obtenir le symbole de devise associé, utilisez `product.price?.currencySymbol`. | | **Subscription Period** | Pour afficher la période (ex. semaine, mois, année, etc.), utilisez `product.subscription?.localizedSubscriptionPeriod`. Cette localisation est basée sur la locale de l'appareil. Pour récupérer la période d'abonnement par programmation, utilisez `product.subscription?.subscriptionPeriod`. Vous pouvez alors accéder à la propriété `unit` pour obtenir la durée (`'day'`, `'week'`, `'month'`, `'year'` ou `'unknown'`). La valeur `numberOfUnits` vous donnera le nombre d'unités de période. Par exemple, pour un abonnement trimestriel, vous verrez `'month'` dans la propriété unit et `3` dans la propriété numberOfUnits. | | **Introductory Offer** | Pour afficher un badge ou tout autre indicateur signalant qu'un abonnement contient une offre de lancement, consultez la propriété `product.subscription?.offer?.phases`. Il s'agit d'une liste pouvant contenir jusqu'à deux phases de remise : la phase d'essai gratuit et la phase de prix de lancement. Chaque objet de phase contient les propriétés utiles suivantes :
• `paymentMode` : une chaîne avec les valeurs `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` et `'unknown'`. Les essais gratuits correspondent au type `'free_trial'`.
• `price` : le prix réduit sous forme de nombre. Pour les essais gratuits, cette valeur sera `0`.
• `localizedNumberOfPeriods` : une chaîne localisée selon la locale de l'appareil, décrivant la durée de l'offre. Par exemple, une offre d'essai de trois jours affiche `'3 days'` dans ce champ.
• `subscriptionPeriod` : vous pouvez également obtenir les détails individuels de la période de l'offre avec cette propriété. Son fonctionnement est identique à celui décrit dans la section précédente.
• `localizedSubscriptionPeriod` : une période d'abonnement formatée pour la locale de l'utilisateur. | ## Accélérer la récupération du flow avec le flow de l'audience par défaut \{#speed-up-flow-fetching-with-default-audience-flow\} En général, les flows sont récupérés presque instantanément, vous n'avez donc pas à vous inquiéter d'optimiser ce processus. Cependant, si vous avez de nombreuses audiences et placements et que vos utilisateurs disposent d'une connexion internet faible, la récupération d'un flow peut prendre plus de temps que souhaité. Dans ce cas, vous pouvez afficher un flow par défaut pour garantir une expérience utilisateur fluide plutôt que de ne rien afficher du tout. Pour résoudre ce problème, vous pouvez utiliser la méthode `getFlowForDefaultAudience`, qui récupère le flow du placement spécifié pour l'audience **All Users**. Il est toutefois essentiel de comprendre que l'approche recommandée est de récupérer le flow via la méthode `getFlow`, comme décrit dans la section [Récupérer les informations du flow](fetch-paywalls-and-products-capacitor#fetch-flow-information) ci-dessus. :::warning Pourquoi nous recommandons d'utiliser `getFlow` La méthode `getFlowForDefaultAudience` présente quelques inconvénients importants : - **Problèmes potentiels de compatibilité descendante** : Si vous avez besoin d'afficher différents flows pour différentes versions de l'application (actuelle et future), vous pourrez rencontrer des difficultés. Vous devrez soit concevoir des flows compatibles avec la version actuelle (ancienne), soit accepter que les utilisateurs de cette version puissent rencontrer des problèmes avec des flows non rendus. - **Perte de ciblage** : Tous les utilisateurs verront le même flow conçu pour l'audience **All Users**, ce qui signifie que vous perdez le ciblage personnalisé (notamment selon les pays, l'attribution marketing ou vos propres attributs personnalisés). Si vous acceptez ces inconvénients pour bénéficier d'une récupération plus rapide du flow, utilisez la méthode `getFlowForDefaultAudience` comme suit. Sinon, restez sur la méthode `getFlow` décrite [ci-dessus](fetch-paywalls-and-products-capacitor#fetch-flow-information). ::: ```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); } ``` | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements). C'est la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK tente de charger les données depuis le serveur et renvoie les données mises en cache en cas d'échec. Nous recommandons cette option, car elle garantit que vos utilisateurs reçoivent toujours les données les plus récentes.

Toutefois, si vous pensez que vos utilisateurs sont souvent confrontés à une connexion instable, envisagez d'utiliser `'return_cache_data_else_load'` pour renvoyer les données en cache si elles existent. Dans ce cas, les utilisateurs peuvent ne pas obtenir les toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc fiable de l'utiliser en cours de session pour éviter des requêtes réseau.

Notez que le cache reste intact après un redémarrage de l'application et n'est effacé que lors d'une réinstallation ou d'un nettoyage manuel.

|
Avant de pouvoir afficher les Remote Configs et les paywalls personnalisés, vous devez récupérer les informations les concernant. Notez que ce sujet porte sur les Remote Configs et les paywalls personnalisés. Pour obtenir des conseils sur la récupération des paywalls personnalisés avec le Paywall Builder, consultez [Récupérer les paywalls Paywall Builder et leur configuration](capacitor-get-pb-paywalls). :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base. :::
Avant de commencer à récupérer les paywalls et les produits dans votre application mobile (cliquez pour développer) 1. [Créez vos produits](create-product) dans l'Adapty Dashboard. 2. [Créez un paywall et intégrez les produits dans votre paywall](create-paywall) dans l'Adapty Dashboard. 3. [Créez des placements et intégrez votre paywall dans le placement](create-placement) dans l'Adapty Dashboard. 4. [Installez le SDK Adapty](sdk-installation-capacitor) dans votre application mobile.
## Récupérer les informations d'un paywall \{#fetch-paywall-information\} Dans Adapty, un [produit](product) regroupe des produits provenant à la fois de l'App Store et de Google Play. Ces produits multiplateformes sont intégrés dans des paywalls, ce qui vous permet de les afficher dans des placements spécifiques de votre application mobile. Pour afficher les produits, vous devez obtenir un [Paywall](paywalls) depuis l'un de vos [placements](placements) avec la méthode `getPaywall`. ```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); } ``` | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements). C'est la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la [localisation du paywall](add-remote-config-locale). Ce paramètre doit être un code de langue composé d'un ou plusieurs sous-tags séparés par le caractère moins (**-**). Le premier sous-tag correspond à la langue, le second à la région.

Exemple : `en` désigne l'anglais, `pt-br` représente le portugais brésilien.

Consultez [Localisations et codes de langue](capacitor-localizations-and-locale-codes) pour plus d'informations sur les codes de langue et notre recommandation d'utilisation.

| | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK tente de charger les données depuis le serveur et retourne les données en cache en cas d'échec. Nous recommandons cette option car elle garantit que vos utilisateurs disposent toujours des données les plus récentes.

Cependant, si vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour retourner les données en cache si elles existent. Dans ce cas, les utilisateurs n'auront pas forcément les toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, ce qui permet de l'utiliser en toute sécurité pendant la session afin d'éviter des requêtes réseau inutiles.

Notez que le cache est conservé après un redémarrage de l'application et n'est effacé que lors d'une réinstallation ou d'un nettoyage manuel.

| | **params.loadTimeoutMs** |

optionnel

par défaut : 5000 ms

|

Cette valeur limite le délai d'attente (en millisecondes) pour cette méthode. Si le délai est dépassé, les données en cache ou le fallback local sont retournés.

Notez que dans de rares cas, cette méthode peut expirer légèrement après le délai spécifié dans `loadTimeoutMs`, car l'opération peut impliquer plusieurs requêtes en coulisse.

| **N'intégrez pas les identifiants produit en dur dans votre code.** Le seul identifiant à coder en dur est l'identifiant de placement. Les paywalls sont configurés à distance, donc le nombre de produits et d'offres disponibles peut changer à tout moment. Votre application doit gérer ces changements de façon dynamique — si un paywall retourne deux produits aujourd'hui et trois demain, affichez-les tous sans modifier le code. Paramètres de réponse : | Paramètre | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objet [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) contenant : une liste d'identifiants de produits, l'identifiant du paywall, le Remote Config, et plusieurs autres propriétés. | ## Récupérer les produits \{#fetch-products\} Une fois que vous disposez du paywall, vous pouvez récupérer le tableau de produits qui lui correspond : ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ paywall }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` Paramètres de la réponse : | Paramètre | Description | | :-------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Liste d'objets [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) comprenant : identifiant du produit, nom du produit, prix, devise, durée de l'abonnement, et plusieurs autres propriétés. | Lors de la mise en œuvre de votre propre design de paywall, vous aurez probablement besoin d'accéder à ces propriétés depuis l'objet [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct). Les propriétés les plus couramment utilisées sont illustrées ci-dessous, mais consultez le document lié pour obtenir tous les détails sur l'ensemble des propriétés disponibles. | Propriété | Description | |--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Titre** | Pour afficher le titre du produit, utilisez `product.localizedTitle`. La localisation est basée sur le pays du store sélectionné par l'utilisateur, et non sur la langue de l'appareil. | | **Prix** | Pour afficher une version localisée du prix, utilisez `product.price?.localizedString`. Cette localisation est basée sur les informations de langue de l'appareil. Vous pouvez également accéder au prix sous forme numérique avec `product.price?.amount`. La valeur est fournie dans la devise locale. Pour obtenir le symbole de devise associé, utilisez `product.price?.currencySymbol`. | | **Période d'abonnement** | Pour afficher la période (ex. : semaine, mois, an, etc.), utilisez `product.subscription?.localizedSubscriptionPeriod`. Cette localisation est basée sur la langue de l'appareil. Pour récupérer la période d'abonnement de façon programmatique, utilisez `product.subscription?.subscriptionPeriod`. Vous pouvez ensuite accéder à la propriété `unit` pour obtenir la durée unitaire (`'day'`, `'week'`, `'month'`, `'year'` ou `'unknown'`). La valeur `numberOfUnits` indique le nombre d'unités de la période. Par exemple, pour un abonnement trimestriel, `unit` vaut `'month'` et `numberOfUnits` vaut `3`. | | **Offre de lancement** | Pour afficher un badge ou un indicateur signalant qu'un abonnement inclut une offre de lancement, consultez la propriété `product.subscription?.offer?.phases`. C'est une liste pouvant contenir jusqu'à deux phases de remise : la phase d'essai gratuit et la phase de prix de lancement. Chaque objet de phase contient les propriétés utiles suivantes :
• `paymentMode` : une chaîne avec les valeurs `'free_trial'`, `'pay_as_you_go'`, `'pay_up_front'` et `'unknown'`. Les essais gratuits correspondent au type `'free_trial'`.
• `price` : le prix remisé sous forme numérique. Pour les essais gratuits, cette valeur est `0`.
• `localizedNumberOfPeriods` : une chaîne localisée selon la langue de l'appareil décrivant la durée de l'offre. Par exemple, une offre d'essai de trois jours affiche `'3 days'` dans ce champ.
• `subscriptionPeriod` : vous pouvez également obtenir les détails individuels de la période d'offre grâce à cette propriété. Son fonctionnement est identique à celui décrit dans la section précédente pour les abonnements.
• `localizedSubscriptionPeriod` : une période d'abonnement formatée pour la remise, dans la langue de l'utilisateur. | ## Accélérer la récupération des paywalls avec le paywall de l'audience par défaut \{#speed-up-paywall-fetching-with-default-audience-paywall\} En règle générale, les paywalls sont récupérés presque instantanément, vous n'avez donc pas à vous soucier d'accélérer ce processus. Cependant, si vous avez de nombreuses audiences et paywalls et que vos utilisateurs disposent d'une connexion internet faible, la récupération d'un paywall peut prendre plus de temps que souhaité. Dans ce cas, vous pouvez afficher un paywall par défaut pour garantir une expérience utilisateur fluide plutôt que de ne rien afficher du tout. Pour y remédier, vous pouvez utiliser la méthode `getPaywallForDefaultAudience`, qui récupère le paywall du placement spécifié pour l'audience **All Users**. Cependant, il est essentiel de comprendre que l'approche recommandée consiste à récupérer le paywall via la méthode `getPaywall`, comme expliqué dans la section [Récupérer les informations du paywall](fetch-paywalls-and-products-capacitor#fetch-paywall-information) ci-dessus. :::warning Pourquoi nous recommandons d'utiliser `getPaywall` La méthode `getPaywallForDefaultAudience` présente quelques inconvénients majeurs : - **Problèmes potentiels de compatibilité ascendante** : Si vous devez afficher des paywalls différents selon les versions de l'application (version actuelle et futures versions), vous risquez de rencontrer des difficultés. Vous devrez soit concevoir des paywalls compatibles avec la version actuelle (legacy), soit accepter que les utilisateurs de cette version puissent rencontrer des problèmes avec des paywalls non affichés. - **Perte de ciblage** : Tous les utilisateurs verront le même paywall conçu pour l'audience **All Users**, ce qui signifie que vous perdez le ciblage personnalisé (notamment selon les pays, l'attribution marketing ou vos propres attributs personnalisés). Si vous acceptez ces inconvénients pour bénéficier d'une récupération plus rapide des paywalls, utilisez la méthode `getPaywallForDefaultAudience` comme suit. Sinon, restez sur la méthode `getPaywall` décrite [ci-dessus](fetch-paywalls-and-products-capacitor#fetch-paywall-information). ::: ```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); } ``` | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements). Il s'agit de la valeur que vous avez spécifiée lors de la création d'un placement dans votre Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la [localisation du paywall](add-remote-config-locale). Ce paramètre doit être un code de langue composé d'un ou plusieurs sous-tags séparés par le caractère moins (**-**). Le premier sous-tag désigne la langue, le second la région.

Exemple : `en` signifie l'anglais, `pt-br` représente le portugais brésilien.

Consultez [Localisations et codes de langue](capacitor-localizations-and-locale-codes) pour en savoir plus sur les codes de langue et notre façon de les utiliser.

| | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK tente de charger les données depuis le serveur et renvoie les données en cache en cas d'échec. Nous recommandons cette option, car elle garantit que vos utilisateurs obtiennent toujours les données les plus récentes.

Toutefois, si vos utilisateurs ont souvent une connexion instable, envisagez d'utiliser `'return_cache_data_else_load'` pour renvoyer les données en cache lorsqu'elles existent. Dans ce cas, les utilisateurs ne disposeront peut-être pas des toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sans risque de l'utiliser au cours d'une session pour éviter les requêtes réseau.

Notez que le cache est conservé après un redémarrage de l'application et n'est effacé qu'en cas de désinstallation ou de nettoyage manuel.

|
--- # File: present-remote-config-paywalls-capacitor --- --- title: "Afficher un paywall conçu via Remote Config dans le SDK Capacitor" description: "Découvrez comment présenter des paywalls Remote Config dans le SDK Adapty Capacitor pour personnaliser l'expérience utilisateur." --- Si vous avez personnalisé un flow via Remote Config, vous devrez implémenter le rendu dans le code de votre application mobile pour l'afficher aux utilisateurs. Comme Remote Config offre une flexibilité adaptée à vos besoins, vous contrôlez ce qui est inclus et la façon dont votre vue de flow apparaît. Nous fournissons une méthode pour récupérer la configuration distante, vous laissant toute liberté pour présenter votre flow personnalisé configuré via Remote Config. ## Récupérer la Remote Config du flow et l'afficher \{#get-flow-remote-config-and-present-it\} Dans la v4, un flow contient une entrée `AdaptyRemoteConfig` par langue configurée dans le tableau `remoteConfigs`. Choisissez la langue qui correspond à la préférence de l'utilisateur, puis lisez les valeurs dont vous avez besoin depuis son `data`. ```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); } ``` À ce stade, une fois toutes les valeurs nécessaires reçues, il est temps de les assembler en une page visuellement attrayante. Assurez-vous que le design s'adapte aux différentes tailles d'écran et orientations des appareils mobiles, pour une expérience fluide et conviviale sur tous les terminaux. :::warning Veillez à [enregistrer l'événement d'affichage du paywall](present-remote-config-paywalls-capacitor#track-paywall-view-events) comme décrit ci-dessous, afin qu'Adapty Analytics puisse capturer les informations pour les entonnoirs et les tests A/B. ::: Une fois l'affichage du flow terminé, poursuivez en configurant le flux d'achat. Lorsque l'utilisateur effectue un achat, appelez simplement `.makePurchase()` avec le produit de votre flow. Pour plus de détails sur la méthode `.makePurchase()`, consultez [Effectuer des achats](capacitor-making-purchases). Nous recommandons de [créer un paywall de secours appelé fallback paywall](capacitor-use-fallback-paywalls). Ce paywall de secours s'affichera à l'utilisateur en l'absence de connexion internet ou de cache disponible, garantissant une expérience fluide même dans ces situations. ## Suivre les événements d'affichage du paywall \{#track-paywall-view-events\} Adapty vous aide à mesurer les performances de vos flows. Bien que nous collectons automatiquement les données sur les achats, l'enregistrement des affichages de flows nécessite votre intervention, car vous seul savez quand un client voit un flow. Pour enregistrer un événement d'affichage de flow, appelez simplement `.logShowFlow({ flow })` — il sera alors reflété dans vos métriques de paywall dans les entonnoirs et les tests A/B. :::important Il n'est pas nécessaire d'appeler `.logShowFlow({ flow })` si vous affichez des flows ou des paywalls rendus par le [Flow Builder](adapty-flow-builder) ou le [Paywall Builder](adapty-paywall-builder). Adapty suit les affichages automatiquement dans ces cas. ::: ```typescript showLineNumbers await adapty.logShowFlow({ flow }); ``` Paramètres de la requête : | Paramètre | Présence | Description | | :-------- | :------- |:-------------------------------------------------------------------------------------| | **flow** | requis | Un objet `AdaptyFlow` obtenu via `adapty.getFlow({ placementId })`. | Si vous avez personnalisé un paywall via Remote Config, vous devrez implémenter le rendu dans le code de votre application mobile pour l'afficher aux utilisateurs. Comme Remote Config offre une flexibilité adaptée à vos besoins, vous contrôlez ce qui est inclus et la façon dont votre vue de paywall apparaît. Nous fournissons une méthode pour récupérer la configuration distante, vous laissant toute liberté pour présenter votre paywall personnalisé configuré via Remote Config. ## Récupérer la Remote Config du paywall et l'afficher \{#get-paywall-remote-config-and-present-it\} Pour obtenir la Remote Config d'un paywall, accédez à la propriété `remoteConfig` et extrayez les valeurs nécessaires. ```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); } ``` À ce stade, une fois toutes les valeurs nécessaires reçues, il est temps de les assembler en une page visuellement attrayante. Assurez-vous que le design s'adapte aux différentes tailles d'écran et orientations des appareils mobiles, pour une expérience fluide et conviviale sur tous les terminaux. :::warning Veillez à [enregistrer l'événement d'affichage du paywall](present-remote-config-paywalls-capacitor#track-paywall-view-events-1) comme décrit ci-dessous, afin qu'Adapty Analytics puisse capturer les informations pour les entonnoirs et les tests A/B. ::: Une fois l'affichage du paywall terminé, poursuivez en configurant le flux d'achat. Lorsque l'utilisateur effectue un achat, appelez simplement `.makePurchase()` avec le produit de votre paywall. Pour plus de détails sur la méthode `.makePurchase()`, consultez [Effectuer des achats](capacitor-making-purchases). Nous recommandons de [créer un paywall de secours appelé fallback paywall](capacitor-use-fallback-paywalls). Ce paywall de secours s'affichera à l'utilisateur en l'absence de connexion internet ou de cache disponible, garantissant une expérience fluide même dans ces situations. ## Suivre les événements d'affichage du paywall \{#track-paywall-view-events-1\} Adapty vous aide à mesurer les performances de vos paywalls. Bien que nous collectons automatiquement les données sur les achats, l'enregistrement des affichages de paywalls nécessite votre intervention, car vous seul savez quand un client voit un paywall. Pour enregistrer un événement d'affichage de paywall, appelez simplement `.logShowPaywall(paywall)` — il sera alors reflété dans vos métriques de paywall dans les entonnoirs et les tests A/B. :::important Il n'est pas nécessaire d'appeler `.logShowPaywall(paywall)` si vous affichez des paywalls créés dans le [Paywall Builder](adapty-paywall-builder). ::: ```typescript showLineNumbers try { await adapty.logShowPaywall({ paywall }); } catch (error) { console.error('Failed to log paywall view:', error); } ``` Paramètres de la requête : | Paramètre | Présence | Description | | :---------- | :------- | :--------------------------------------------------------- | | **paywall** | requis | Un objet [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall). | --- # File: capacitor-making-purchases --- --- title: "Make purchases in mobile app in Capacitor SDK" description: "Guide on handling in-app purchases and subscriptions using Adapty." --- Afficher des paywalls dans votre application mobile est une étape essentielle pour donner aux utilisateurs accès à des contenus ou services premium. Cependant, se contenter d'afficher ces paywalls suffit à gérer les achats uniquement si vous utilisez le [Paywall Builder](adapty-paywall-builder) pour personnaliser vos paywalls. Si vous n'utilisez pas le Paywall Builder, vous devez utiliser une méthode distincte appelée `.makePurchase()` pour finaliser un achat et débloquer le contenu souhaité. Cette méthode sert de point d'entrée pour que les utilisateurs interagissent avec les paywalls et effectuent leurs transactions. Si votre paywall comporte une offre promotionnelle active pour le produit qu'un utilisateur souhaite acheter, Adapty l'appliquera automatiquement au moment de l'achat. Assurez-vous d'avoir effectué la [configuration initiale](quickstart) sans sauter une seule étape. Sans cela, nous ne pouvons pas valider les achats. ## Effectuer un achat \{#make-purchase\} :::note **Vous utilisez le [Paywall Builder](adapty-paywall-builder) ?** Les achats sont traités automatiquement — vous pouvez ignorer cette étape. **Vous cherchez un guide pas à pas ?** Consultez le [guide de démarrage rapide](capacitor-implement-paywalls-manually) pour des instructions d'implémentation complètes avec tout le contexte nécessaire. ::: ```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); } ``` Paramètres de la requête : | Paramètre | Présence | Description | | :---------- | :------- |:----------------------------------------------------------------------------------------------------------------------------| | **product** | requis | Un objet [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) récupéré depuis le flow via `getPaywallProducts`. | Paramètres de la réponse : | Paramètre | Description | |---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **result** | Un objet [`AdaptyPurchaseResult`](https://capacitor.adapty.io/types/adaptypurchaseresult) avec un champ `type` indiquant le résultat de l'achat (`'success'`, `'user_cancelled'` ou `'pending'`) et un champ `profile` contenant l'[`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) mis à jour en cas d'achat réussi. | ## Changer d'abonnement lors d'un achat \{#change-subscription-when-making-a-purchase\} Lorsqu'un utilisateur opte pour un nouvel abonnement plutôt que de renouveler l'abonnement actuel, le comportement dépend du store : - Pour l'App Store, l'abonnement est mis à jour automatiquement au sein du groupe d'abonnements. Si un utilisateur achète un abonnement d'un groupe alors qu'il en a déjà un d'un autre groupe, les deux abonnements seront actifs en même temps. - Pour Google Play, l'abonnement n'est pas mis à jour automatiquement. Vous devez gérer le changement dans le code de votre application mobile comme décrit ci-dessous. Pour remplacer un abonnement par un autre sur Android, appelez la méthode `.makePurchase()` avec le paramètre supplémentaire suivant : ```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); } ``` Paramètre de requête supplémentaire : | Paramètre | Présence | Description | | :--------- | :------- | :----------------------------------------------------------- | | **params** | optionnel | Un objet de type [`MakePurchaseParamsInput`](https://capacitor.adapty.io/types/makepurchaseparamsinput) contenant les paramètres d'achat spécifiques à chaque plateforme. | La structure `MakePurchaseParamsInput` comprend : ```typescript { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } ``` Vous pouvez en savoir plus sur les abonnements et les modes de remplacement dans la documentation Google Developer : - [À propos des modes de remplacement](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recommandations de Google pour les modes de remplacement](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Mode de remplacement [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Remarque : cette méthode n'est disponible que pour les mises à niveau d'abonnement. Les rétrogradations ne sont pas prises en charge. - Mode de remplacement [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Remarque : le changement d'abonnement effectif n'intervient qu'à la fin de la période de facturation de l'abonnement en cours. ### Gérer les plans prépayés (Android) \{#manage-prepaid-plans-android\} Si les utilisateurs de votre application peuvent acheter des [plans prépayés](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) (par exemple, souscrire un abonnement non renouvelable pour plusieurs mois), vous pouvez activer les [transactions en attente](https://developer.android.com/google/play/billing/subscriptions#pending) pour les plans prépayés. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { pendingPrepaidPlansEnabled: true, }, } }); ``` ## Utiliser des codes de réduction sur iOS \{#redeem-offer-codes-in-ios\}
À propos des codes d'offre Les codes d'offre vous permettent d'accorder des réductions ou des périodes d'essai gratuites à des utilisateurs spécifiques. Contrairement aux offres classiques appliquées automatiquement, les codes d'offre sont distribués en dehors de l'application — par e-mail, réseaux sociaux ou supports imprimés. Les utilisateurs les activent en saisissant le code dans l'App Store, en suivant une URL de validation ou via une boîte de dialogue intégrée à l'application. Pour configurer des codes d'offre, ouvrez un abonnement dans App Store Connect et accédez à sa section **Offer Codes**. Vous pouvez créer [trois types](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) de codes d'offre : - **Free** — l'abonnement est gratuit pendant une durée définie, puis le renouvellement suivant se fait au plein tarif. - **Pay as you go** — l'utilisateur paie un tarif réduit à chaque cycle de facturation pendant une durée définie, puis l'abonnement se renouvelle au plein tarif. - **Pay up front** — l'utilisateur paie un prix unique réduit pour toute la durée de l'offre, puis l'abonnement se renouvelle au plein tarif. Vous n'avez pas besoin d'ajouter les codes d'offre à Adapty. Apple marque chaque transaction pendant la période d'offre avec la catégorie du code d'offre. Cela inclut la première activation et tous les renouvellements à tarif réduit qui suivent. Adapty détecte ce marquage et enregistre chaque transaction avec la catégorie d'offre `offer_code`. Une fois la période d'offre terminée et l'abonnement renouvelé au plein tarif, le marquage disparaît. Vous pouvez filtrer les analyses par le type d'offre **Offer Code** dans l'[Adapty Dashboard](controls-filters-grouping-compare-proceeds). #### Résolution des écarts de revenus \{#revenue-discrepancy-troubleshooting\} Si vous constatez qu'une transaction avec code d'offre apparaît dans Adapty au prix plein du produit plutôt qu'au prix réduit de l'offre, vérifiez les points suivants dans App Store Connect : - Le code d'offre dispose bien d'une tarification correcte configurée pour toutes les régions où les utilisateurs peuvent l'activer. - Le prix de l'offre est défini pour le pays ou la région spécifique de l'utilisateur. Apple envoie le prix régional dans la transaction. Si aucun prix régional n'est configuré pour l'offre, Apple peut envoyer le prix plein du produit à la place. Vous pouvez filtrer et vérifier les transactions avec code d'offre dans l'[Adapty Dashboard](controls-filters-grouping-compare-proceeds) à l'aide des filtres de type d'offre **Offer Code** et **Offer Discount Type**. #### Anciens codes promo (obsolètes) \{#legacy-promo-codes-deprecated\} :::warning Apple a supprimé les codes promo pour les achats intégrés en mars 2026. Les codes d'offre les remplacent avec davantage de fonctionnalités : éligibilité configurable, dates d'expiration et jusqu'à 1 million de codes par trimestre. Si vous utilisiez auparavant des codes promo pour les achats intégrés, passez aux codes d'offre dans App Store Connect. ::: Les anciens codes promo (limités à 100 par application et par version) donnaient un accès gratuit à un abonnement. Contrairement aux codes d'offre, Apple n'incluait pas les informations de réduction dans les transactions avec code promo — il envoyait le prix plein du produit dans le reçu. En conséquence, Adapty enregistrait ces transactions au prix plein, ce qui entraînait des écarts de revenus entre les analyses Adapty et App Store Connect. Si vous constatez des transactions historiques au prix plein qui auraient dû être gratuites, elles proviennent probablement d'anciens codes promo. Ces codes étant désormais obsolètes, passez aux codes d'offre pour un suivi précis des revenus.
Pour afficher la feuille de saisie de code de réduction dans votre application : ```typescript showLineNumbers try { await adapty.presentCodeRedemptionSheet(); } catch (error) { console.error('Failed to present code redemption sheet:', error); } ``` :::danger D'après nos observations, la feuille de saisie de code de réduction peut ne pas fonctionner de manière fiable dans certaines applications. Nous recommandons de rediriger l'utilisateur directement vers l'App Store. Pour ce faire, vous devez ouvrir une URL au format suivant : `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: --- # File: capacitor-restore-purchase --- --- title: "Restaurer les achats dans une application mobile avec le SDK Capacitor" description: "Découvrez comment restaurer les achats dans Adapty pour garantir une expérience utilisateur fluide." --- La restauration des achats sur iOS et Android est une fonctionnalité qui permet aux utilisateurs de récupérer l'accès à du contenu précédemment acheté — abonnements ou achats intégrés — sans être facturés à nouveau. Cette fonctionnalité est particulièrement utile pour les utilisateurs qui ont désinstallé puis réinstallé l'application, ou qui ont changé d'appareil et souhaitent retrouver leur contenu sans payer une nouvelle fois. :::note Dans les paywalls créés avec le [Paywall Builder](adapty-paywall-builder), les achats sont restaurés automatiquement sans code supplémentaire de votre part. Si c'est votre cas, vous pouvez ignorer cette étape. ::: Pour restaurer un achat si vous n'utilisez pas le [Paywall Builder](adapty-paywall-builder) pour personnaliser votre paywall, appelez la méthode `.restorePurchases()` : ```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); } ``` Paramètres de la réponse : | Paramètre | Description | |-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | Un objet [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile). Ce modèle contient des informations sur les niveaux d'accès, les abonnements et les achats uniques. Vérifiez le **statut du niveau d'accès** pour déterminer si l'utilisateur a accès à l'application. | --- # File: implement-observer-mode-capacitor --- --- title: "Implémenter le mode Observateur dans le SDK Capacitor" description: "Implémentez le mode Observateur dans Adapty pour suivre les événements d'abonnement des utilisateurs dans le SDK Capacitor." --- Si vous disposez déjà de votre propre infrastructure d'achat et n'êtes pas encore prêt à basculer entièrement vers Adapty, vous pouvez explorer le [mode Observateur](observer-vs-full-mode). Dans sa forme de base, le mode Observateur offre des analyses avancées et une intégration transparente avec les systèmes d'attribution et d'analytique. Si cela correspond à vos besoins, vous devez uniquement : 1. L'activer lors de la configuration du SDK Adapty en définissant le paramètre `observerMode` sur `true`. Suivez les instructions de configuration pour [Capacitor](sdk-installation-capacitor#activate-adapty-module-of-adapty-sdk). 2. [Signaler les transactions](report-transactions-observer-mode-capacitor) depuis votre infrastructure d'achat existante vers Adapty. :::tip Dans le SDK v4, vous pouvez également afficher des flows et des paywalls rendus par Adapty en mode Observateur : lorsqu'un utilisateur appuie sur le bouton d'achat ou de restauration, le SDK transmet l'action à votre code afin que vous puissiez effectuer l'achat ou la restauration vous-même. Voir [Afficher des flows en mode Observateur](capacitor-present-flows-in-observer-mode). ::: ### Configuration du mode Observateur \{#observer-mode-setup\} Activez le mode Observateur si vous gérez vous-même les achats et l'état des abonnements, et utilisez Adapty uniquement pour envoyer des événements d'abonnement et des données analytiques. :::important Lorsqu'il fonctionne en mode Observateur, le SDK Adapty ne fermera aucune transaction — assurez-vous de le gérer vous-même. ::: ```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); } ``` Paramètres : | Paramètre | Description | | --------------------------- | ------------------------------------------------------------ | | **observerMode** | Une valeur booléenne qui contrôle le [mode Observateur](observer-vs-full-mode). La valeur par défaut est `false`. | ## Utiliser les paywalls Adapty en mode Observateur \{#using-adapty-paywalls-in-observer-mode\} Si vous souhaitez également utiliser les paywalls et les fonctionnalités de test A/B d'Adapty, c'est possible — mais cela nécessite une configuration supplémentaire en mode Observateur. Voici ce que vous devrez faire en plus des étapes ci-dessus : 1. Affichez les paywalls comme d'habitude pour les [paywalls Remote Config](present-remote-config-paywalls-capacitor). 2. [Associez les paywalls](report-transactions-observer-mode-capacitor) aux transactions d'achat. --- # File: report-transactions-observer-mode-capacitor --- --- title: "Signaler les transactions en mode Observateur dans le SDK Capacitor" description: "Signalez les transactions d'achat en mode Observateur d'Adapty pour le suivi des utilisateurs et des revenus dans le SDK Capacitor." --- En mode Observateur, le SDK Adapty ne peut pas suivre automatiquement les achats effectués via votre système d'achat existant. Vous devez signaler les transactions depuis votre store. Il est indispensable de configurer cela **avant** de publier votre application pour éviter les erreurs dans les analyses. Utilisez `reportTransaction` pour signaler explicitement chaque transaction afin qu'Adapty la reconnaisse. :::warning **Ne sautez pas le signalement des transactions !** Si vous n'appelez pas `reportTransaction`, Adapty ne reconnaîtra pas la transaction, elle n'apparaîtra pas dans les analyses et ne sera pas envoyée aux intégrations. ::: Si vous utilisez les paywalls Adapty, incluez le `variationId` lors du signalement d'une transaction. Cela associe l'achat au paywall qui l'a déclenché, garantissant ainsi des analyses de paywall précises. ```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); } ``` Paramètres : | Paramètre | Présence | Description | | ------------- | -------- | ------------------------------------------------------------ | | **transactionId** | obligatoire |
  • Pour iOS : Identifiant de la transaction.
  • Pour Android : Identifiant de type chaîne (`purchase.getOrderId`) de l'achat, où l'achat est une instance de la classe [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la bibliothèque de facturation.
| | **variationId** | optionnel | L'identifiant de type chaîne de la variante. Vous pouvez l'obtenir via la propriété `variationId` de l'objet [AdaptyPaywall](https://capacitor.adapty.io/interfaces/adaptypaywall). | --- # File: capacitor-user --- --- title: "Utilisateurs et accès" description: "Découvrez comment gérer les utilisateurs et les niveaux d'accès dans votre application Capacitor avec le SDK Adapty." --- --- # File: capacitor-identifying-users --- --- title: "Identifier les utilisateurs dans le SDK Capacitor" description: "Découvrez comment identifier les utilisateurs dans votre application Capacitor avec le SDK Adapty." --- Adapty crée un identifiant de profil interne pour chaque utilisateur. Cependant, si vous avez votre propre système d'authentification, vous devez définir votre propre Customer User ID. Vous pouvez retrouver les utilisateurs par leur Customer User ID dans la section [Profiles](profiles-crm) et l'utiliser dans l'[API côté serveur](getting-started-with-server-side-api), qui sera envoyé à toutes les intégrations. ### Définir le customer user ID lors de la configuration \{#setting-customer-user-id-on-configuration\} Si vous disposez d'un identifiant utilisateur lors de la configuration, transmettez-le simplement en tant que paramètre `customerUserId` à la méthode `.activate()` : ```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); } ``` ### Définir le customer user ID après la configuration \{#setting-customer-user-id-after-configuration\} Si vous ne disposez pas d'un identifiant utilisateur lors de la configuration du SDK, vous pouvez le définir ultérieurement à tout moment avec la méthode `.identify()`. Les cas d'usage les plus courants pour cette méthode sont après une inscription ou une authentification, lorsque l'utilisateur passe du statut d'utilisateur anonyme à celui d'utilisateur authentifié. ```typescript showLineNumbers try { await adapty.identify({ customerUserId: 'YOUR_USER_ID' }); console.log('User identified successfully'); } catch (error) { console.error('Failed to identify user:', error); } ``` Paramètres de la requête : | Paramètre | Présence | Description | |---------|--------|-----------| | **customerUserId** | requis | Un identifiant utilisateur de type chaîne de caractères. | :::warning Resoumission des données utilisateur importantes Dans certains cas, par exemple lorsqu'un utilisateur se reconnecte à son compte, les serveurs d'Adapty disposent déjà d'informations sur cet utilisateur. Dans ce cas, le SDK Adapty basculera automatiquement vers le nouvel utilisateur. Si vous avez transmis des données à l'utilisateur anonyme, telles que des attributs personnalisés ou des attributions provenant de réseaux tiers, vous devez resoumettre ces données pour l'utilisateur identifié. Il est également important de noter que vous devez redemander tous les paywalls et produits après avoir identifié l'utilisateur, car les données du nouvel utilisateur peuvent être différentes. ::: ### Déconnexion et connexion \{#logging-out-and-logging-in\} Vous pouvez déconnecter l'utilisateur à tout moment en appelant la méthode `.logout()` : ```typescript showLineNumbers try { await adapty.logout(); console.log('User logged out successfully'); } catch (error) { console.error('Failed to logout user:', error); } ``` Vous pouvez ensuite connecter l'utilisateur en utilisant la méthode `.identify()`. ## Attribuer un `appAccountToken` (iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) est un **UUID** qui vous permet de lier les transactions App Store à votre identité utilisateur interne. StoreKit associe ce token à chaque transaction, afin que votre backend puisse faire correspondre les données App Store à vos utilisateurs. Utilisez un UUID stable généré par utilisateur et réutilisez-le pour le même compte sur tous les appareils. Cela garantit que les achats et les notifications App Store restent correctement associés. Vous pouvez définir le token de deux façons : lors de l'activation du SDK ou lors de l'identification de l'utilisateur. :::important Vous devez toujours passer `appAccountToken` conjointement avec `customerUserId`. Si vous ne transmettez que le token, il ne sera pas inclus dans la transaction. ::: ```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' }, } }); ``` ### Définir des identifiants de compte masqués (Android) \{#set-obfuscated-account-ids-android\} Google Play exige des identifiants de compte masqués pour certains cas d'usage afin de renforcer la confidentialité et la sécurité des utilisateurs. Ces identifiants permettent à Google Play d'identifier les achats tout en préservant l'anonymat des informations utilisateur, ce qui est particulièrement important pour la prévention des fraudes et l'analyse. Vous devrez peut-être définir ces identifiants si votre application traite des données utilisateur sensibles ou si vous êtes tenu de respecter des réglementations spécifiques en matière de confidentialité. Les identifiants masqués permettent à Google Play de suivre les achats sans exposer les identifiants utilisateur réels. ```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' }, } }); ``` ## Détecter les utilisateurs sur plusieurs appareils \{#detect-users-across-devices\} Lors de l'activation du SDK, il lit automatiquement les droits existants de l'utilisateur depuis StoreKit (iOS) ou Google Play Billing (Android) et les synchronise avec le backend Adapty. Un abonnement actif apparaît sur le profil Adapty sans que l'application n'appelle `restorePurchases`. Ce qui **ne** se produit **pas** automatiquement, c'est la reconnaissance qu'un profil sur un nouvel appareil appartient au même utilisateur que le profil sur l'appareil d'origine. Adapty fait correspondre les profils par Customer User ID, donc la continuité d'identité dépend de ce que vous utilisez comme CUID. **Ce qu'Adapty peut détecter entre les appareils** | Votre configuration | Ce qu'Adapty détecte | Ce que vous devez faire | | --- | --- | --- | | Customer User ID = `device_id` (sans connexion à l'application) | Le nouvel appareil reçoit un CUID différent et donc un profil différent. L'abonnement se synchronise avec le nouveau profil via un événement **Access level updated**, mais `subscription_started` ne se déclenche pas — le nouveau profil est traité comme un héritier de l'achat d'origine. Les analyses basées sur `subscription_started` sous-compteront les utilisateurs de retour. | Utilisez un identifiant de compte stable comme Customer User ID pour qu'un utilisateur de retour corresponde au profil existant sur tous les appareils. | | Customer User ID = identifiant de compte stable (connexion sur chaque appareil) | Le SDK synchronise automatiquement l'abonnement lors de l'appel `activate()`, et `identify()` fait correspondre le profil existant par CUID. | Aucune configuration supplémentaire n'est nécessaire — l'identité et l'abonnement se résolvent automatiquement. | | Héritier du partage familial Apple | Le membre de la famille reçoit l'abonnement uniquement via un événement **Access level updated** — `subscription_started` ne se déclenche pas. | Écoutez **Access level updated**. Consultez [Apple Family Sharing](apple-family-sharing) pour la matrice complète des événements. | | Même compte Apple/Google, utilisateurs in-app différents | Le premier profil à enregistrer l'achat devient le parent. Les profils suivants voient l'abonnement via une chaîne d'héritiers, avec un seul événement **Access level updated**. | Exigez une connexion, puis choisissez un [mode de partage](sharing-paid-access-between-user-accounts) adapté à votre modèle. | **Restaurer les achats sur un nouvel appareil** Proposez un bouton « Restaurer les achats » initié par l'utilisateur sur votre paywall. Les directives App Review d'Apple (règle 3.1.1) l'exigent, et il sert de solution de secours quand la synchronisation automatique rate un cas limite. Ce bouton doit appeler `restorePurchases` dans votre SDK. Un appel programmatique à `restorePurchases` au premier lancement n'est pas nécessaire pour une utilisation normale — le SDK effectue déjà l'équivalent lors de l'appel `activate()`. Réservez les appels programmatiques pour forcer une vérification fraîche du reçu, par exemple lors du débogage d'un accès manquant après la fin de `activate()`. --- # File: capacitor-setting-user-attributes --- --- title: "Définir les attributs utilisateur dans le SDK Capacitor" description: "Découvrez comment mettre à jour les attributs utilisateur et les données de profil dans votre application Capacitor avec le SDK Adapty." --- Vous pouvez définir des attributs optionnels tels que l'e-mail, le numéro de téléphone, etc., pour les utilisateurs de votre application. Vous pouvez ensuite utiliser ces attributs pour créer des [segments](segments) d'utilisateurs ou simplement les consulter dans le CRM. ### Définir les attributs utilisateur \{#setting-user-attributes\} Pour définir les attributs utilisateur, appelez la méthode `.updateProfile()` : ```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); } ``` Notez que les attributs que vous avez précédemment définis avec la méthode `updateProfile` ne seront pas réinitialisés. :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base. ::: ### Liste des clés autorisées \{#the-allowed-keys-list\} Les clés autorisées de `AdaptyProfileParameters` et leurs valeurs sont listées ci-dessous : | Clé | Valeur | |---|-----| | **email** | String | | **phoneNumber** | String | | **firstName** | String | | **lastName** | String | | **gender** | Enum, les valeurs autorisées sont : `'female'`, `'male'`, `'other'` | | **birthday** | Chaîne de date au format ISO | ### Attributs utilisateur personnalisés \{#custom-user-attributes\} Vous pouvez définir vos propres attributs personnalisés. Ceux-ci sont généralement liés à l'utilisation de votre application. Par exemple, pour une application de fitness, il peut s'agir du nombre d'exercices par semaine ; pour une application d'apprentissage des langues, du niveau de connaissance de l'utilisateur, etc. Vous pouvez les utiliser dans des segments pour créer des paywalls et des offres ciblées, et dans les analyses pour déterminer quelles métriques produit influencent le plus le chiffre d'affaires. ```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); } ``` Pour supprimer des clés existantes, passez `null` comme valeur : ```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); } ``` Il peut arriver que vous ayez besoin de savoir quels attributs personnalisés ont déjà été définis. Pour cela, utilisez le champ `customAttributes` de l'objet `AdaptyProfile`. :::warning Gardez à l'esprit que la valeur de `customAttributes` peut être obsolète, car les attributs utilisateur peuvent être envoyés depuis différents appareils à tout moment — les attributs sur le serveur ont donc pu être modifiés depuis la dernière synchronisation. ::: ### Limites \{#limits\} - Jusqu'à 30 attributs personnalisés par utilisateur - Les noms de clé peuvent comporter jusqu'à 30 caractères. Ils peuvent contenir des caractères alphanumériques ainsi que les caractères suivants : `_` `-` `.` - La valeur peut être une chaîne de caractères ou un nombre flottant, avec 50 caractères maximum. --- # File: capacitor-listen-subscription-changes --- --- title: "Vérifier le statut d'abonnement dans le SDK Capacitor" description: "Suivez et gérez le statut d'abonnement des utilisateurs dans Adapty pour améliorer la rétention client dans votre application Capacitor." --- Avec Adapty, suivre le statut d'abonnement est simple. Pas besoin d'insérer manuellement des identifiants de produits dans votre code. Il vous suffit de vérifier la présence d'un [niveau d'accès](access-level) actif pour confirmer l'état de l'abonnement d'un utilisateur.
Avant de vérifier le statut d'abonnement (cliquez pour développer) - Pour iOS, configurez les [notifications serveur App Store](enable-app-store-server-notifications) - Pour Android, configurez les [notifications en temps réel pour les développeurs (RTDN)](enable-real-time-developer-notifications-rtdn)
## Niveau d'accès et objet AdaptyProfile \{#access-level-and-the-adaptyprofile-object\} Les niveaux d'accès sont des propriétés de l'objet [AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile). Nous recommandons de récupérer le profil au démarrage de l'application, par exemple lors de [l'identification d'un utilisateur](capacitor-identifying-users#setting-customer-user-id-on-configuration), puis de le mettre à jour à chaque changement. Ainsi, vous pouvez utiliser l'objet profil sans avoir à le redemander sans cesse. Pour être notifié des mises à jour du profil, écoutez les changements comme décrit dans la section [Écouter les mises à jour du profil, y compris les niveaux d'accès](capacitor-listen-subscription-changes) ci-dessous. :::tip Vous souhaitez voir un exemple concret d'intégration du SDK Adapty dans une application mobile ? Consultez nos [exemples d'applications](sample-apps), qui illustrent la configuration complète, notamment l'affichage des paywalls, les achats et d'autres fonctionnalités de base. ::: ## Récupérer le niveau d'accès depuis le serveur \{#retrieving-the-access-level-from-the-server\} Pour obtenir le niveau d'accès depuis le serveur, utilisez la méthode `.getProfile()` : ```typescript showLineNumbers try { const profile = await adapty.getProfile(); console.log('Profile retrieved successfully'); } catch (error) { console.error('Failed to get profile:', error); } ``` Paramètres de réponse : | Paramètre | Description | | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | Un objet [AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile). En général, il suffit de vérifier le statut du niveau d'accès du profil pour déterminer si l'utilisateur bénéficie d'un accès premium. La méthode `.getProfile` renvoie le résultat le plus récent en interrogeant toujours l'API. Si, pour une raison quelconque (par exemple, absence de connexion Internet), le SDK Adapty ne parvient pas à récupérer les informations depuis le serveur, les données du cache sont renvoyées. Il est également important de noter que le SDK Adapty met régulièrement à jour le cache `AdaptyProfile` pour que ces informations restent aussi récentes que possible. | La méthode `.getProfile()` vous fournit le profil utilisateur depuis lequel vous pouvez obtenir le statut du niveau d'accès. Vous pouvez avoir plusieurs niveaux d'accès par application. Par exemple, si vous avez une application de presse et vendez des abonnements à différentes thématiques indépendamment, vous pouvez créer les niveaux d'accès « sports » et « science ». Mais la plupart du temps, un seul niveau d'accès suffit — dans ce cas, vous pouvez simplement utiliser le niveau d'accès « premium » par défaut. Voici un exemple pour vérifier le niveau d'accès « premium » par défaut : ```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); } ``` ### Écouter les mises à jour du statut d'abonnement \{#listening-for-subscription-status-updates\} Chaque fois que l'abonnement d'un utilisateur change, Adapty déclenche un événement. Pour recevoir des messages d'Adapty, vous devez effectuer une configuration supplémentaire : ```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 déclenche également un événement au démarrage de l'application. Dans ce cas, le statut d'abonnement mis en cache est transmis. ### Cache du statut d'abonnement \{#subscription-status-cache\} Le cache intégré au SDK Adapty stocke le statut d'abonnement du profil. Cela signifie que même si le serveur est indisponible, les données mises en cache restent accessibles pour fournir des informations sur le statut d'abonnement du profil. Il est toutefois important de noter qu'il n'est pas possible d'interroger directement le cache. Le SDK interroge périodiquement le serveur toutes les minutes pour détecter les mises à jour ou changements liés au profil. Si des modifications sont détectées — nouvelles transactions ou autres mises à jour — elles sont appliquées aux données en cache afin de les synchroniser avec le serveur. --- # File: capacitor-deal-with-att --- --- title: "Gérer l'ATT dans le SDK Capacitor" description: "Commencez avec Adapty sur Capacitor pour simplifier la configuration et la gestion des abonnements." --- Si votre application utilise le framework AppTrackingTransparency et présente une demande d'autorisation de suivi à l'utilisateur, vous devez envoyer le [statut d'autorisation](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) à Adapty. ```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 Nous vous recommandons vivement d'envoyer cette valeur le plus tôt possible dès qu'elle change — c'est la seule façon de garantir que les données sont transmises en temps voulu aux intégrations que vous avez configurées. ::: --- # File: capacitor-onboardings --- --- title: "Onboardings" description: "Découvrez comment travailler avec les onboardings dans votre application Capacitor avec le SDK Adapty." --- :::warning **Les onboardings sont dépréciés dans le SDK v4 et seront supprimés dans une prochaine version.** Ils ne reçoivent plus de correctifs ni d'améliorations. Utilisez plutôt les [flows](capacitor-get-pb-paywalls) : contrairement aux onboardings qui s'exécutent dans une WebView, les flows s'affichent nativement sur l'appareil — offrant des animations plus fluides, un rendu natif cohérent, des temps de chargement plus rapides et aucune dépendance à un runtime WebView. Consultez [Récupérer les flows et paywalls](capacitor-get-pb-paywalls) et [Afficher les flows et paywalls](capacitor-present-paywalls) pour démarrer. ::: --- # File: capacitor-get-onboardings --- --- title: "Récupérer les onboardings dans le SDK Capacitor" description: "Apprenez à récupérer les onboardings dans Adapty pour Capacitor." --- :::warning **Les onboardings sont dépréciés dans le SDK v4 et seront supprimés dans une prochaine version.** Ils ne bénéficient plus de correctifs ni d'améliorations. Utilisez plutôt les [flows](capacitor-get-pb-paywalls) : contrairement aux onboardings qui s'exécutent dans une WebView, les flows s'affichent nativement sur l'appareil — avec des animations plus fluides, un rendu natif cohérent, des temps de chargement réduits et aucune dépendance à un runtime WebView. Consultez [Obtenir des flows & paywalls](capacitor-get-pb-paywalls) et [Afficher des flows & paywalls](capacitor-present-paywalls) pour démarrer. ::: Après avoir [conçu la partie visuelle de votre onboarding](design-onboarding) avec le builder dans l'Adapty Dashboard, vous pouvez l'afficher dans votre application Capacitor. La première étape consiste à récupérer l'onboarding associé au placement ainsi que sa configuration d'affichage, comme décrit ci-dessous. Avant de commencer, assurez-vous de : 1. Avoir [créé un onboarding](create-onboarding). 2. Avoir ajouté l'onboarding à un [placement](placements). ## Récupérer un onboarding \{#fetch-onboarding\} Lorsque vous créez un [onboarding](onboardings) avec notre builder no-code, il est stocké sous forme de conteneur avec une configuration que votre application doit récupérer et afficher. Ce conteneur gère toute l'expérience — le contenu affiché, la manière dont il est présenté, et la façon dont les interactions utilisateur (comme les réponses à un quiz ou les saisies de formulaire) sont traitées. Le conteneur suit également automatiquement les événements analytiques, vous n'avez donc pas besoin d'implémenter un suivi des vues séparément. Pour de meilleures performances, récupérez la configuration de l'onboarding en avance afin de laisser suffisamment de temps aux images pour se télécharger avant l'affichage. Pour obtenir un onboarding, utilisez la méthode `getOnboarding` : ```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); } ``` Appelez ensuite la méthode `createOnboardingView` pour créer une instance de vue. :::warning Le résultat de la méthode `createOnboardingView` ne peut être utilisé qu'une seule fois. Si vous avez besoin de l'utiliser à nouveau, appelez à nouveau la méthode `createOnboardingView`. ::: ```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'); } ``` Paramètres : | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements) souhaité. C'est la valeur que vous avez indiquée lors de la création d'un placement dans l'Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la localisation de l'onboarding. Ce paramètre doit être un code de langue composé d'un ou deux sous-tags séparés par le caractère moins (**-**). Le premier sous-tag correspond à la langue, le second à la région.

Exemple : `en` signifie anglais, `pt-br` représente le portugais brésilien.

Consultez [Localisations et codes de langue](localizations-and-locale-codes) pour plus d'informations sur les codes de langue et nos recommandations d'utilisation.

| | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK essaie de charger les données depuis le serveur et retourne les données en cache en cas d'échec. Nous recommandons cette option car elle garantit que vos utilisateurs reçoivent toujours les données les plus récentes.

Cependant, si vous pensez que vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour retourner les données en cache si elles existent. Dans ce cas, les utilisateurs pourraient ne pas obtenir les toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sûr de l'utiliser pendant la session pour éviter les requêtes réseau.

Notez que le cache est conservé lors du redémarrage de l'application et n'est effacé que lors de la désinstallation ou via un nettoyage manuel.

| | **params.loadTimeoutMs** |

optionnel

par défaut : 5000 ms

|

Cette valeur limite le délai d'attente (en millisecondes) pour cette méthode. Si le délai est dépassé, les données en cache ou le fallback local seront retournés.

Notez que dans de rares cas, cette méthode peut expirer légèrement après le délai spécifié dans `loadTimeoutMs`, car l'opération peut impliquer différentes requêtes en arrière-plan.

| Paramètres de réponse : | Paramètre | Description | |:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding** | Un objet [`AdaptyOnboarding`](https://capacitor.adapty.io/interfaces/adaptyonboarding) contenant : l'identifiant et la configuration de l'onboarding, le Remote Config, et plusieurs autres propriétés. | ## Accélérer la récupération de l'onboarding avec l'onboarding d'audience par défaut \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} En général, les onboardings sont récupérés presque instantanément, vous n'avez donc pas à vous soucier d'accélérer ce processus. Cependant, si vous avez de nombreuses audiences et onboardings et que vos utilisateurs ont une connexion internet faible, la récupération d'un onboarding peut prendre plus de temps que souhaité. Dans ce cas, vous pouvez afficher un onboarding par défaut pour garantir une bonne expérience utilisateur plutôt que de n'afficher aucun onboarding. Pour cela, vous pouvez utiliser la méthode `getOnboardingForDefaultAudience`, qui récupère l'onboarding du placement spécifié pour l'audience **All Users**. Il est cependant essentiel de comprendre que l'approche recommandée reste de récupérer l'onboarding avec la méthode `getOnboarding`, comme décrit dans la section [Récupérer un onboarding](#fetch-onboarding) ci-dessus. :::warning Préférez `getOnboarding` à `getOnboardingForDefaultAudience`, car cette dernière présente des limitations importantes : - **Problèmes de compatibilité** : peut créer des problèmes lors de la prise en charge de plusieurs versions de l'application, nécessitant soit des designs rétrocompatibles, soit d'accepter que les anciennes versions s'affichent incorrectement. - **Pas de personnalisation** : affiche uniquement le contenu pour l'audience "All Users", sans ciblage basé sur le pays, l'attribution ou des attributs personnalisés. Si la rapidité de récupération justifie ces inconvénients pour votre cas d'usage, utilisez `getOnboardingForDefaultAudience` comme indiqué ci-dessous. Sinon, utilisez `getOnboarding` comme décrit [ci-dessus](#fetch-onboarding). ::: ```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); } ``` Paramètres : | Paramètre | Présence | Description | |---------|--------|-----------| | **placementId** | requis | L'identifiant du [Placement](placements) souhaité. C'est la valeur que vous avez indiquée lors de la création d'un placement dans l'Adapty Dashboard. | | **locale** |

optionnel

par défaut : `en`

|

L'identifiant de la localisation de l'onboarding. Ce paramètre doit être un code de langue composé d'un ou deux sous-tags séparés par le caractère moins (**-**). Le premier sous-tag correspond à la langue, le second à la région.

Exemple : `en` signifie anglais, `pt-br` représente le portugais brésilien.

Consultez [Localisations et codes de langue](localizations-and-locale-codes) pour plus d'informations sur les codes de langue et nos recommandations d'utilisation.

| | **params.fetchPolicy** |

optionnel

par défaut : `'reload_revalidating_cache_data'`

|

Par défaut, le SDK essaie de charger les données depuis le serveur et retourne les données en cache en cas d'échec. Nous recommandons cette option car elle garantit que vos utilisateurs reçoivent toujours les données les plus récentes.

Cependant, si vous pensez que vos utilisateurs ont une connexion internet instable, envisagez d'utiliser `'return_cache_data_else_load'` pour retourner les données en cache si elles existent. Dans ce cas, les utilisateurs pourraient ne pas obtenir les toutes dernières données, mais les temps de chargement seront plus rapides, quelle que soit la qualité de leur connexion. Le cache est mis à jour régulièrement, il est donc sûr de l'utiliser pendant la session pour éviter les requêtes réseau.

Notez que le cache est conservé lors du redémarrage de l'application et n'est effacé que lors de la désinstallation ou via un nettoyage manuel.

| --- # File: capacitor-present-onboardings --- --- title: "Présenter les onboardings dans le SDK Capacitor" description: "Découvrez comment présenter des onboardings sur Capacitor pour augmenter les conversions et les revenus." --- :::warning **Les onboardings sont dépréciés dans le SDK v4 et seront supprimés dans une prochaine version.** Ils ne reçoivent plus de correctifs ni d'améliorations. Utilisez les [flows](capacitor-get-pb-paywalls) à la place : contrairement aux onboardings, qui s'exécutent dans une WebView, les flows s'affichent nativement sur l'appareil — offrant des animations plus fluides, un aspect natif cohérent, des temps de chargement plus rapides et aucune dépendance à l'exécution WebView. Consultez [Obtenir les flows et paywalls](capacitor-get-pb-paywalls) et [Afficher les flows et paywalls](capacitor-present-paywalls) pour commencer. ::: Si vous avez personnalisé un onboarding à l'aide du builder, vous n'avez pas à vous soucier de son rendu dans le code de votre application mobile pour l'afficher à l'utilisateur. Un tel onboarding contient à la fois ce qui doit être affiché et la façon dont cela doit l'être. Avant de commencer, assurez-vous que : 1. Vous avez [créé un onboarding](create-onboarding). 2. Vous avez ajouté l'onboarding à un [placement](placements). ## Présenter un onboarding \{#present-onboarding\} Pour afficher un onboarding, utilisez la méthode `view.present()` sur la `view` créée par la méthode `createOnboardingView`. Chaque `view` ne peut être utilisée qu'une seule fois. Si vous devez afficher à nouveau l'onboarding, appelez `createOnboardingView` une nouvelle fois pour créer une nouvelle instance de `view`. :::warning Réutiliser la même `view` sans la recréer peut entraîner une erreur. ::: ```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); } ``` ## Configurer le style de présentation iOS \{#configure-ios-presentation-style\} Configurez la façon dont l'onboarding est présenté sur iOS en passant le paramètre `iosPresentationStyle` à la méthode `present()`. Ce paramètre accepte les valeurs `'full_screen'` (par défaut) ou `'page_sheet'`. ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` ## Personnaliser l'ouverture des liens dans les onboardings \{#customize-how-links-open-in-onboardings\} :::important La personnalisation de l'ouverture des liens dans les onboardings est prise en charge à partir du SDK Adapty v3.15. ::: Par défaut, les liens dans les onboardings s'ouvrent dans un navigateur intégré à l'application. Cela offre une expérience utilisateur fluide en affichant les pages web directement dans votre application, permettant aux utilisateurs de les consulter sans changer d'application. Si vous préférez ouvrir les liens dans un navigateur externe, vous pouvez personnaliser ce comportement en définissant le paramètre `openIn` sur `browser_out_app` : ```typescript showLineNumbers await view.present({ openIn: 'browser_out_app' }); // default — browser_in_app ``` ## Étapes suivantes \{#next-steps\} Une fois votre onboarding présenté, vous souhaiterez [gérer les interactions utilisateur et les événements](capacitor-handling-onboarding-events). Découvrez comment gérer les événements d'onboarding pour répondre aux actions des utilisateurs et suivre les analyses. --- # File: capacitor-handling-onboarding-events --- --- title: "Gérer les événements d'onboarding dans le SDK Capacitor" description: "Gérez les événements liés à l'onboarding dans Capacitor avec Adapty." --- :::warning **Les onboardings sont dépréciés dans le SDK v4 et seront supprimés dans une version future.** Ils ne reçoivent plus de correctifs ni d'améliorations. Utilisez les [flows](capacitor-get-pb-paywalls) à la place : contrairement aux onboardings qui s'exécutent dans une WebView, les flows s'affichent nativement sur l'appareil — offrant des animations plus fluides, un rendu natif cohérent, des temps de chargement réduits et aucune dépendance à l'environnement WebView. Consultez [Obtenir des flows et paywalls](capacitor-get-pb-paywalls) et [Afficher des flows et paywalls](capacitor-present-paywalls) pour commencer. ::: Les onboardings configurés avec le builder génèrent des événements auxquels votre application peut réagir. Utilisez la méthode `setEventHandlers` pour gérer ces événements lors d'une présentation d'écran autonome. Avant de commencer, assurez-vous que : 1. Vous avez [créé un onboarding](create-onboarding). 2. Vous avez ajouté l'onboarding à un [placement](placements). ## Configurer les gestionnaires d'événements \{#set-up-event-handlers\} Pour gérer les événements des onboardings, utilisez la méthode `view.setEventHandlers` : ```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); } ``` ## Types d'événements \{#event-types\} Les sections suivantes décrivent les différents types d'événements que vous pouvez gérer. ### Gérer les actions personnalisées \{#handle-custom-actions\} Dans le builder, vous pouvez ajouter une action **personnalisée** à un bouton et lui attribuer un ID. Vous pouvez ensuite utiliser cet ID dans votre code et le traiter comme une action personnalisée. Par exemple, si un utilisateur appuie sur un bouton personnalisé, comme **Login** ou **Allow notifications**, le gestionnaire d'événements sera déclenché avec le paramètre `actionId` correspondant à l'**Action ID** défini dans le builder. Vous pouvez créer vos propres IDs, comme "allowNotifications". ```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 }, }); ```
Exemple d'événement (cliquez pour développer) ```json { "actionId": "allow_notifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
### Fin du chargement de l'onboarding \{#finishing-loading-onboarding\} Cet événement est déclenché lorsqu'un onboarding termine son chargement : ```typescript showLineNumbers view.setEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ```
Exemple d'événement (cliquez pour développer) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
### Fermeture de l'onboarding \{#closing-onboarding\} L'onboarding est considéré comme fermé lorsqu'un utilisateur appuie sur un bouton auquel l'action **Close** est assignée. :::important Notez que vous devez gérer ce qui se passe lorsqu'un utilisateur ferme l'onboarding. Par exemple, vous devez arrêter d'afficher l'onboarding lui-même. ::: ```typescript showLineNumbers view.setEventHandlers({ onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, }); ```
Exemple d'événement (cliquez pour développer) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
### Ouverture d'un paywall \{#opening-a-paywall\} :::tip Gérez cet événement pour ouvrir un paywall si vous souhaitez l'afficher à l'intérieur de l'onboarding. Si vous voulez ouvrir un paywall après la fermeture de l'onboarding, il existe une approche plus directe : gérez l'action de fermeture et ouvrez un paywall sans vous appuyer sur les données de l'événement. ::: La façon la plus fluide d'utiliser les paywalls dans les onboardings est de définir l'ID d'action égal à l'ID de placement du paywall. Notez que, sur iOS, une seule vue (paywall ou onboarding) peut être affichée à l'écran à la fois. Si vous présentez un paywall par-dessus un onboarding, vous ne pouvez pas contrôler l'onboarding en arrière-plan par programme. Tenter de fermer l'onboarding fermera le paywall à la place, laissant l'onboarding visible. Pour éviter cela, fermez toujours la vue de l'onboarding avant de présenter le paywall. ```typescript showLineNumbers view.setEventHandlers({ onPaywall(actionId, meta) { // Dismiss onboarding before presenting paywall view.dismiss().then(() => { openPaywall(actionId); }); }, }); async function openPaywall(placementId: string) { // Implement your paywall opening logic here } ```
Exemple d'événement (cliquez pour développer) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
### Suivi de la navigation \{#tracking-navigation\} Vous recevez un événement d'analytics lorsque différents événements liés à la navigation se produisent pendant le flow d'onboarding : ```typescript showLineNumbers view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event.type, meta.onboardingId); }, }); ``` L'objet `event` peut être de l'un des types suivants : |Type | Description | |------------|-------------| | `onboardingStarted` | Lorsque l'onboarding a été chargé | | `screenPresented` | Lorsqu'un écran est affiché | | `screenCompleted` | Lorsqu'un écran est complété. Inclut un `elementId` optionnel (identifiant de l'élément complété) et un `reply` optionnel (réponse de l'utilisateur). Déclenché quand les utilisateurs effectuent une action pour quitter l'écran. | | `secondScreenPresented` | Lorsque le deuxième écran est affiché | | `userEmailCollected` | Déclenché lorsque l'e-mail de l'utilisateur est collecté via le champ de saisie | | `onboardingCompleted` | Déclenché lorsqu'un utilisateur atteint un écran avec l'ID `final`. Si vous avez besoin de cet événement, [assignez l'ID `final` au dernier écran](design-onboarding). | | `unknown` | Pour tout type d'événement non reconnu. Inclut `name` (le nom de l'événement inconnu) et `meta` (métadonnées supplémentaires) | Chaque événement inclut des informations `meta` contenant : | Champ | Description | |------------|-------------| | `onboardingId` | Identifiant unique du flow d'onboarding | | `screenClientId` | Identifiant de l'écran actuel | | `screenIndex` | Position de l'écran actuel dans le flow | | `screensTotal` | Nombre total d'écrans dans le flow |
Exemples d'événements (cliquez pour développer) ```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: capacitor-onboarding-input --- --- title: "Traiter les données des onboardings dans le SDK Capacitor" description: "Enregistrez et utilisez les données des onboardings dans votre app Capacitor avec le SDK Adapty." --- :::warning **Les onboardings sont dépréciés dans le SDK v4 et seront supprimés dans une prochaine version.** Ils ne reçoivent plus de correctifs ni d'améliorations. Utilisez plutôt les [flows](capacitor-get-pb-paywalls) : contrairement aux onboardings qui s'exécutent dans une WebView, les flows s'affichent nativement sur l'appareil — vous bénéficiez ainsi d'animations plus fluides, d'un rendu natif cohérent, de temps de chargement plus rapides et d'aucune dépendance au runtime WebView. Consultez [Récupérer les flows & paywalls](capacitor-get-pb-paywalls) et [Afficher les flows & paywalls](capacitor-present-paywalls) pour démarrer. ::: Lorsque vos utilisateurs répondent à une question de quiz ou saisissent des données dans un champ de saisie, la méthode `onStateUpdated` est appelée. Vous pouvez enregistrer ou traiter le type de champ dans votre code. Par exemple : ```typescript view.setEventHandlers({ onStateUpdated(action, meta) { // Process data }, }); ``` Consultez le format des actions [ici](https://capacitor.adapty.io/types/onboardingstateupdatedaction).
Exemples de données enregistrées (le format peut différer selon votre implémentation) ```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 } } } ```
## Cas d'utilisation \{#use-cases\} ### Enrichir les profils utilisateurs avec des données \{#enrich-user-profiles-with-data\} Si vous souhaitez associer immédiatement les données saisies au profil utilisateur et éviter de lui demander deux fois les mêmes informations, vous devez [mettre à jour le profil utilisateur](capacitor-setting-user-attributes) avec les données saisies lors du traitement de l'action. Par exemple, vous demandez aux utilisateurs de saisir leur nom dans un champ texte avec l'ID `name`, et vous souhaitez définir la valeur de ce champ comme prénom de l'utilisateur. Vous leur demandez également de saisir leur e-mail dans le champ `email`. Dans le code de votre app, cela peut ressembler à ceci : ```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 }); } } }, }); ``` ### Personnaliser les paywalls en fonction des réponses \{#customize-paywalls-based-on-answers\} En utilisant des quiz dans les onboardings, vous pouvez également personnaliser les paywalls affichés aux utilisateurs après qu'ils ont terminé l'onboarding. Par exemple, vous pouvez interroger les utilisateurs sur leur expérience sportive et afficher des CTA et des produits différents selon les groupes d'utilisateurs. 1. [Ajoutez un quiz](onboarding-quizzes) dans le builder d'onboarding et attribuez des IDs significatifs à ses options. 2. Traitez les réponses au quiz en fonction de leurs IDs et [définissez des attributs personnalisés](capacitor-setting-user-attributes) pour les utilisateurs. ```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. [Créez des segments](segments) pour chaque valeur d'attribut personnalisé. 4. Créez un [placement](placements) et ajoutez des [audiences](audience) pour chaque segment créé. 5. [Affichez un paywall](capacitor-paywalls) pour le placement dans le code de votre app. Si votre onboarding comporte un bouton qui ouvre un paywall, implémentez le code du paywall en tant que [réponse à l'action de ce bouton](capacitor-handling-onboarding-events#opening-a-paywall). --- # File: capacitor-best-practices --- --- title: "Bonnes pratiques avec le SDK Capacitor" description: "Modèles de référence pour intégrer le SDK Adapty sur Capacitor — ordre d'appel, gestion des erreurs et autres règles de préparation à la production." --- --- # File: capacitor-sdk-call-order --- --- title: "Ordre d'appel dans le SDK Capacitor" description: "Évitez la perte d'accès premium, les attributions manquantes et les erreurs #2002 intermittentes en appelant les méthodes du SDK Adapty dans le bon ordre." --- `adapty.activate()` doit se terminer avant tout autre appel à une méthode du SDK Adapty. Tant qu'il n'a pas résolu, le SDK n'a aucun état. Tout appel émis avant ou en parallèle d'`activate()` échoue avec [`#2002 notActivated`](capacitor-handle-errors#custom-network-codes). Si votre application authentifie des utilisateurs et que vous récupérez un identifiant utilisateur client après le lancement, appelez `adapty.identify()` à ce moment-là. N'appelez pas les méthodes liées aux actions utilisateur tant qu'`identify` n'a pas résolu. Les appels en concurrence avec celui-ci échouent soit avec [`#3006 profileWasChanged`](capacitor-handle-errors#custom-network-codes), soit atterrissent sur le profil anonyme créé à l'activation. Quand cela se produit, l'attribution, les identifiants MMP comme `appsflyer_id`, et la propriété de l'installation ne sont pas toujours transférés vers le profil identifié. Si votre application n'authentifie pas les utilisateurs, ignorez `identify` et continuez à travailler avec le profil anonyme. Les SDK MMP et analytiques (AppsFlyer, Adjust, Branch, PostHog) suivent la même règle. Initialisez-les en premier et attendez leurs callbacks UID avant d'appeler `adapty.activate`. Sinon, l'identifiant MMP atterrit sur un profil anonyme éphémère et n'est pas toujours transféré vers le profil identifié. Pour les spécificités d'AppsFlyer, consultez [AppsFlyer](appsflyer). ## L'ordre correct \{#the-correct-order\} Votre chemin dépend de deux choses : quand vous connaissez l'identifiant utilisateur client, et si vous utilisez un SDK MMP ou analytique. - **Étapes 2 et 5** : Obligatoires pour chaque application. Activez le SDK, puis appelez les méthodes du SDK. - **Étapes 1 et 3** : Requises uniquement si vous intégrez un SDK MMP ou analytique (AppsFlyer, Adjust, Branch, PostHog). - **Étape 4** : Requise uniquement si votre application authentifie des utilisateurs et récupère l'identifiant utilisateur client après le lancement. Si vous avez l'identifiant utilisateur client au lancement de l'application, passez-le directement dans `activate()` (étape 2a). Ce chemin ne crée jamais de profil anonyme, donc l'étape 4 est inutile. | Étape | Appel | Quand | Remarques | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | Initialisez votre SDK MMP ou analytique (AppsFlyer, Adjust, PostHog, Branch) | Lancement de l'app, en premier | Attendez le callback UID du MMP, par exemple `getAppsFlyerUID`. | | 2a | `adapty.activate({ apiKey: '...', params: { customerUserId: '...' } })` | Lancement de l'app, après l'étape 1, si vous avez l'identifiant utilisateur client | Recommandé. Aucun profil anonyme n'est jamais créé. | | 2b | `adapty.activate({ apiKey: '...' })` sans `customerUserId` | Lancement de l'app, après l'étape 1, si vous n'avez pas l'identifiant utilisateur client (ou ne le collectez jamais) | Adapty crée un profil anonyme. | | 3 | `adapty.setIntegrationIdentifier({ key: '...', value: '...' })` pour chaque MMP | Après l'étape 2, avant tout appel lié à une action utilisateur | Requis pour que les identifiants MMP atterrissent sur le bon profil. | | 4 | `await adapty.identify({ customerUserId: 'YOUR_USER_ID' })` | Après l'étape 3 (ou l'étape 2 sans MMP), avant l'étape 5 — uniquement sur le chemin 2b avec authentification | Toujours `await`. Les appels concurrents pendant `identify` produisent `#3006 profileWasChanged`. | | 5 | `getPaywall` (`getFlow` dans le SDK v4), `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | Après l'étape 4 si vous appelez `identify` ; sinon après l'étape 3 (ou l'étape 2 sans MMP) | Ces appels nécessitent un profil stable. | :::important Ignorer ces étapes entraîne une perte d'accès premium pour les utilisateurs existants, un `appsflyer_id` manquant sur les profils, et des paywalls retournés pour la mauvaise audience. ::: ## Installations web2app et web-funnel \{#web2app-and-web-funnel-installs\} Si des utilisateurs achètent via un paiement web (Stripe, Paddle) et installent ensuite l'application native, le premier `activate()` de l'appareil crée un nouveau profil anonyme. Ce profil n'est pas lié au profil web. Si vous pouvez résoudre l'identifiant utilisateur client avant le lancement de l'application (depuis votre flow d'authentification ou le referrer d'installation), passez-le directement dans `activate()`. Sinon, l'achat web est invisible sur l'appareil tant que vous n'avez pas appelé `identify({ customerUserId: 'YOUR_USER_ID' })` puis `restorePurchases`. Pour les métadonnées à envoyer avec chaque paiement web, consultez : - [Stripe](stripe) - [Paddle](paddle) --- # File: capacitor-optimize-paywall-fetching --- --- title: "Optimiser la récupération des paywalls dans le SDK Capacitor" description: "Récupérez les paywalls Adapty de façon fiable : timing, mise en cache et stratégies de secours pour Capacitor." --- Une récupération fiable de paywall sur Capacitor repose sur trois principes : un affichage rapide, le retour du paywall ciblé par audience, et un repli fluide en cas de réseau lent. Les règles ci-dessous couvrent le timing, la mise en cache et les stratégies de secours pour y parvenir. :::tip Ces règles supposent que `adapty.activate()` et `adapty.identify()` ont déjà résolu. Consultez [Ordre des appels dans le SDK Capacitor](capacitor-sdk-call-order). ::: Les conseils ci-dessous utilisent les noms de méthodes de la v3. Dans le SDK v4, `getPaywall` est renommé en `getFlow` (voir le [guide de migration](migration-to-capacitor-sdk-v4)) — toutes les règles s'appliquent sans modification. ## Règles et pièges à éviter \{#rules-and-pitfalls\} | À faire | À ne pas faire | Pourquoi | |---|---|---| | Récupérez le placement que vous êtes sur le point d'afficher. | Ne pré-récupérez pas tous les placements simultanément au lancement. | La pré-récupération en masse bloque le thread principal et provoque un écran noir pendant la rafale. | | Appelez `getPaywall` après que l'attribution a eu le temps de se résoudre — par exemple, 1 à 2 secondes après `activate` ou après le déclenchement du listener `onLatestProfileLoad`. | N'appelez pas `getPaywall` au lancement de l'app dans `App.tsx`. | L'attribution n'est pas encore disponible. Le paywall se résout sur l'audience par défaut et contourne silencieusement les segments et la personnalisation ASA. | | Définissez un `loadTimeoutMs` et configurez un [paywall de secours](fallback-paywalls) pour chaque placement. | N'attendez pas indéfiniment sur `getPaywall`. | Sans timeout, les utilisateurs sur une connexion médiocre voient un écran blanc jusqu'à ce que le réseau réponde — ou ferment l'app. | Consultez [Récupérer les paywalls et les produits](fetch-paywalls-and-products-capacitor) pour la référence des paramètres `fetchPolicy` et `loadTimeoutMs`, et [Placements](placements) pour choisir le bon placement. ## Optimiser pour les connexions médiocres \{#tune-for-poor-connectivity\} Pour les marchés avec une connectivité régulièrement médiocre (zones rurales, transports, régions affectées par le routage) : - Définissez `fetchPolicy: 'return_cache_data_else_load'` sur chaque récupération sauf la toute première. - Configurez un [paywall de secours](fallback-paywalls) pour chaque placement dans l'Adapty Dashboard. - Définissez `loadTimeoutMs` entre 3 000 et 5 000 millisecondes et acceptez le paywall de secours lorsque le timeout se déclenche. - Ne bloquez pas l'affichage du paywall sur `adapty.getProfile()`. Appelez `getPaywall` indépendamment pour qu'un profil lent ne bloque pas l'interface. --- # File: capacitor-show-aa-targeted-paywall --- --- title: "Afficher un paywall ciblé AA au premier lancement dans le SDK Capacitor" description: "Affichez un paywall immédiatement et mettez-le à jour pour les utilisateurs Apple Ads une fois l'attribution appliquée dans Capacitor, en utilisant AdaptyProfile.appliedAttributionSources." --- L'attribution Apple Ads (AA) arrive de façon asynchrone après `adapty.activate()`. Au premier lancement, elle n'est généralement pas encore disponible, donc `getFlow` se résout par rapport à l'audience par défaut et les utilisateurs Apple Ads ratent votre paywall segmenté AA. Plutôt que de retarder le paywall jusqu'à la réception de l'attribution, affichez-en un immédiatement et actualisez-le dès que l'attribution AA est appliquée — ainsi, les utilisateurs Apple Ads voient la variante ciblée et les autres voient un paywall sans attente. `AdaptyProfile.appliedAttributionSources` vous indique quand l'attribution AA a été appliquée. ## Avant de commencer \{#before-you-start\} Vous avez besoin de : - SDK Adapty Capacitor **3.17.1** ou version ultérieure. - Apple Ads configuré pour l'application dans Adapty. Voir [Apple Ads](apple-search-ads). ## Fonctionnement \{#how-it-works\} Après `adapty.activate()`, le SDK demande l'attribution Apple Ads à Apple en arrière-plan et transmet le résultat au backend d'Adapty. Quand AA devient la source d'attribution active pour le profil, le SDK envoie un `AdaptyProfile` mis à jour à votre listener `onLatestProfileLoad`, avec `'apple_search_ads'` dans son tableau `appliedAttributionSources`. Cela vous permet de charger le paywall en deux étapes : 1. Appelez `getFlow` immédiatement. Sans attribution appliquée, Adapty résout la requête par rapport à l'audience par défaut, et l'utilisateur voit un paywall tout de suite. 2. Quand `'apple_search_ads'` apparaît, appelez à nouveau `getFlow`. Adapty résout alors la requête par rapport à l'audience Apple Ads et retourne le paywall ciblé, qui remplace le premier. `appliedAttributionSources` peut être vide ou absent. Cela signifie soit : - L'attribution Apple Ads n'a pas encore été traitée pour ce profil, soit - aucune attribution n'est arrivée du tout. Dans tous les cas, l'étape 1 est sans risque — Adapty résout la requête par rapport à l'audience qui correspond à l'état actuel du profil, généralement l'audience par défaut. L'étape 2 ne s'exécute que lorsque `'apple_search_ads'` apparaît. :::important À chaque lancement suivant, le profil en cache contient déjà `'apple_search_ads'` dans `appliedAttributionSources`, donc le premier `getFlow` renvoie déjà le paywall segmenté Apple Ads — il n'y a pas de second appel ni de changement visible. Le flow en deux étapes n'a d'importance qu'au premier lancement, tant que l'attribution est encore en cours de traitement. ::: ## Implémentation \{#implementation\} Affichez un paywall immédiatement, puis écoutez `'apple_search_ads'` et actualisez le paywall dès qu'il arrive. 1. **Activez le SDK.** Voir [Installer et configurer le SDK Capacitor](sdk-installation-capacitor). 2. **Chargez et affichez un paywall** avec `getFlow` comme d'habitude — ne bloquez pas sur l'attribution. 3. **Abonnez-vous aux mises à jour du profil** avec `adapty.addListener('onLatestProfileLoad', …)` et surveillez `'apple_search_ads'`. Quand il apparaît, récupérez à nouveau le paywall et affichez le mis à jour. Si vous n'avez pas encore configuré le listener, voir [Écouter les mises à jour d'abonnement](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. **Arrêtez d'écouter après un délai d'expiration.** La plupart des utilisateurs ne reçoivent jamais d'attribution Apple Ads, donc supprimez le listener au bout d'un moment plutôt que de le garder ouvert pour toute la session. Configurez un [paywall de secours](capacitor-use-fallback-paywalls) pour le placement afin que l'utilisateur voie toujours quelque chose en cas d'échec d'une requête. ## Exemple complet \{#complete-example\} `onAppleAdsAttribution` se résout dès que l'attribution Apple Ads est appliquée, ou rejette après `timeoutMs`. L'utilisation ci-dessous charge un paywall immédiatement, puis le récupère à nouveau quand l'attribution arrive — les utilisateurs Apple Ads obtiennent le paywall ciblé, et si l'attribution n'arrive jamais, le premier paywall reste en place : ```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 { return new Promise((resolve, reject) => { let timer: ReturnType | 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'); }); ``` Au premier lancement, un utilisateur Apple Ads voit brièvement le paywall par défaut avant qu'il soit remplacé. Si vous affichez des paywalls avec le Paywall Builder, décidez si la re-présentation est acceptable, ou appliquez la mise à jour uniquement avant que le paywall soit affiché. Ajustez `timeoutMs` en fonction du temps pendant lequel vous souhaitez garder l'écoute active — l'attribution qui arrive le fait généralement en quelques secondes après le lancement. Si votre application écoute déjà `onLatestProfileLoad` à d'autres fins (par exemple, [vérifier le statut de l'abonnement](capacitor-check-subscription-status#listen-to-subscription-updates)), vous n'avez pas besoin de le modifier. `adapty.addListener` prend en charge plusieurs listeners indépendants, donc celui-ci s'ajoute sans affecter les autres. --- # File: capacitor-test --- --- title: "Test & release in Capacitor SDK" description: "Apprenez à tester et publier votre application Capacitor avec le SDK Adapty." --- Si vous avez déjà intégré le SDK Adapty dans votre application Capacitor, vous voudrez vérifier que tout est correctement configuré et que les achats fonctionnent comme prévu sur iOS et Android. Cela implique de tester à la fois l'intégration du SDK et le flux d'achat réel avec l'environnement sandbox d'Apple et l'environnement de test de Google Play. ## Tester votre application \{#test-your-app\} Pour des tests complets de vos achats intégrés, consultez nos guides de test par plateforme : [guide de test iOS](test-purchases-in-sandbox) et [guide de test Android](testing-on-android). ## Préparer la publication \{#prepare-for-release\} Avant de soumettre votre application au store, suivez la [Liste de vérification avant publication](release-checklist) pour confirmer que : - La connexion au store et les notifications serveur sont configurées - Les achats s'effectuent et sont bien remontés à Adapty - L'accès se déverrouille et se restaure correctement - Les exigences en matière de confidentialité et de validation sont respectées --- # File: kids-mode-capacitor --- --- title: "Mode Enfants dans le SDK Capacitor" description: "Activez facilement le Mode Enfants pour respecter les politiques d'Apple et Google. Aucune donnée IDFA, GAID ou publicitaire collectée dans le SDK Capacitor." --- Si votre application Capacitor est destinée aux enfants, vous devez respecter les politiques d'[Apple](https://developer.apple.com/kids/) et de [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si vous utilisez le SDK Adapty, quelques étapes simples vous permettront de le configurer pour répondre à ces politiques et passer les révisions des stores. ## Ce qui est requis \{#whats-required\} Vous devez configurer le SDK Adapty pour désactiver la collecte de : - [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) - [Adresse IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) De plus, nous vous recommandons d'utiliser l'identifiant utilisateur client avec précaution. Un identifiant au format `` sera clairement considéré comme une collecte de données personnelles, tout comme l'utilisation d'un e-mail. Pour le Mode Enfants, la bonne pratique consiste à utiliser des identifiants aléatoires ou anonymisés (par exemple, des IDs hachés ou des UUIDs générés par l'appareil) pour assurer la conformité. ## Activer le Mode Enfants \{#enabling-kids-mode\} ### Modifications dans l'Adapty Dashboard \{#updates-in-the-adapty-dashboard\} Dans l'Adapty Dashboard, vous devez désactiver la collecte des adresses IP. Pour ce faire, rendez-vous dans [App settings](https://app.adapty.io/settings/general) et cliquez sur **Disable IP address collection** sous **Collect users' IP address**. ### Modifications dans le code de votre application mobile \{#updates-in-your-mobile-app-code\} Pour respecter les politiques, désactivez la collecte de l'IDFA, du GAID et de l'adresse IP de l'utilisateur : ```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); } ``` ### Configurations spécifiques à chaque plateforme \{#platform-specific-configurations\} #### iOS \{#ios\} Même avec la collecte IDFA désactivée dans le code (ci-dessus), votre build inclut toujours les frameworks `AdSupport` et `AppTrackingTransparency`. La catégorie Enfants de l'App Store ne les autorise pas. Et comme le SDK v4 installe le SDK iOS natif via Swift Package Manager, il n'y a pas d'étape Podfile pour les supprimer. Pour respecter les exigences d'Apple, ajoutez la commande `adapty-kids-mode` fournie avec le SDK dans le `postinstall` de votre application. Elle active le trait `KidsMode` du SDK, qui exclut ce code à la compilation. La commande se réapplique à chaque installation : ```json showLineNumbers title="package.json" { "scripts": { "postinstall": "adapty-kids-mode" } } ``` Réinstallez ensuite et résolvez à nouveau les packages iOS, puis compilez avec **Xcode 26** ou une version ultérieure : ```sh showLineNumbers title="Shell" npm install npx cap sync ios ``` Pour désactiver le Mode Enfants, exécutez `adapty-kids-mode disable` et synchronisez à nouveau. Si vous utilisez CocoaPods pour iOS, vous pouvez également activer le Mode Enfants au niveau natif : 1. Mettez à jour votre Podfile : - Si vous **n'avez pas** de section `post_install`, ajoutez l'intégralité du bloc de code ci-dessous. - Si vous **avez déjà** une section `post_install`, intégrez les lignes mises en évidence dedans. ```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. Exécutez la commande suivante pour appliquer les modifications : ```sh showLineNumbers title="Shell" pod install ``` #### Android : supprimer la permission d'identifiant publicitaire \{#android-remove-the-advertising-id-permission\} Définir `adIdCollectionDisabled: true` (ci-dessus) empêche Adapty de collecter l'identifiant publicitaire, mais le SDK déclare toujours la permission `AD_ID`. Si votre application cible **uniquement** les enfants et est compilée pour Android 13 (API 33) ou supérieur, Google Play vous interdit même de la demander. Effectuez deux ajouts dans votre élément `` : 1. Déclarez le namespace `tools` (le manifeste par défaut de Capacitor l'omet). 2. Ajoutez une entrée `` pour `AD_ID` avec `tools:node="remove"` afin de la supprimer. ```xml showLineNumbers title="android/app/src/main/AndroidManifest.xml" ``` ## Étapes suivantes \{#next-steps\} Une fois le Mode Enfants activé, assurez-vous de : 1. Tester votre application en profondeur pour vérifier que toutes les fonctionnalités fonctionnent correctement 2. Mettre à jour la politique de confidentialité de votre application pour refléter la désactivation de la collecte de données 3. Soumettre votre application pour révision avec une documentation claire sur la conformité au Mode Enfants Pour plus d'informations sur les exigences spécifiques à chaque plateforme : - [Mode Enfants dans le SDK iOS](kids-mode) pour les détails de configuration iOS supplémentaires - [Mode Enfants dans le SDK Android](kids-mode-android) pour les détails de configuration Android supplémentaires --- # File: capacitor-reference --- --- title: "Référence" description: "Documentation de référence pour l'Adapty Capacitor SDK." --- Cette page contient la documentation de référence pour l'Adapty Capacitor SDK. Choisissez le sujet dont vous avez besoin : - **[Modèles SDK](https://capacitor.adapty.io/)** - Modèles de données et structures utilisés par le SDK - **[Gérer les erreurs](capacitor-handle-errors)** - Gestion des erreurs et résolution des problèmes --- # File: capacitor-handle-errors --- --- title: "Gérer les erreurs dans le SDK Capacitor" description: "Gérer les erreurs dans le SDK Capacitor." --- Chaque erreur retournée par le SDK est une instance d'`AdaptyError`. Voici un exemple : :::tip **Activez les logs verbeux avant de déboguer.** La plupart des `AdaptyError` encapsulent une erreur sous-jacente de StoreKit, Play Billing, réseau ou backend. Avec les logs verbeux activés (`adapty.setLogLevel({ logLevel: 'verbose' })` — voir [Logging](sdk-installation-capacitor#logging)), cette erreur encapsulée s'affiche dans la console, ce qui vous indique généralement la cause réelle. La propriété `detail` d'`AdaptyError` est renseignée quel que soit le niveau de log — les logs verbeux la font simplement apparaître dans la console. ::: ```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); } } ``` ## Propriétés des erreurs \{#error-properties\} La classe `AdaptyError` expose les propriétés suivantes : | Propriété | Type | Description | |----------|------|-------------| | `adaptyCode` | `number` | Code d'erreur numérique (ex. : `1003` pour cantMakePayments) | | `localizedDescription` | `string` | Message d'erreur compréhensible par l'utilisateur | | `detail` | `string \| undefined` | Détails supplémentaires sur l'erreur (optionnel) | | `message` | `string` | Message d'erreur complet incluant le code et la description | ## Codes d'erreur \{#error-codes\} Le SDK exporte des constantes et des utilitaires pour travailler avec les codes d'erreur : ### Constante ErrorCodeName \{#errorcodename-constant\} Associe des identifiants textuels à des codes numériques : ```typescript ErrorCodeName.cantMakePayments // 1003 ErrorCodeName.notActivated // 2002 ErrorCodeName.networkFailed // 2005 ``` ### Constante ErrorCode \{#errorcode-constant\} Associe des codes numériques à des identifiants textuels : ```typescript ErrorCode[1003] // 'cantMakePayments' ErrorCode[2002] // 'notActivated' ErrorCode[2005] // 'networkFailed' ``` ### Fonctions utilitaires \{#helper-functions\} ```typescript // Get numeric code from string name: getErrorCode('cantMakePayments') // 1003 // Get string name from numeric code: getErrorPrompt(1003) // 'cantMakePayments' ``` ### Comparer les codes d'erreur \{#comparing-error-codes\} **Important :** `error.adaptyCode` est un **nombre**, il faut donc le comparer directement avec des codes numériques : ```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]) { } ``` ## Gestionnaire d'erreurs global \{#global-error-handler\} Vous pouvez configurer un gestionnaire d'erreurs global pour intercepter toutes les erreurs Adapty : ```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...'); } }; ``` ## Patterns courants de gestion des erreurs \{#common-error-handling-patterns\} ### Gérer les erreurs d'achat \{#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); } } } } ``` ### Gérer les erreurs réseau \{#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; } } ``` ## Codes StoreKit système \{#system-storekit-codes\} | Erreur | Code | Description | |-----|----|-----------| | unknown | 0 | Cette erreur indique qu'une erreur inconnue ou inattendue s'est produite. | | clientInvalid | 1 | Ce code d'erreur indique que le client n'est pas autorisé à effectuer l'action tentée. | | paymentCancelled | 2 |

Ce code d'erreur indique que l'utilisateur a annulé une demande de paiement.

Aucune action n'est requise, mais en termes de logique métier, vous pouvez proposer une remise à votre utilisateur ou lui rappeler plus tard.

| | paymentInvalid | 3 | Cette erreur indique que l'un des paramètres de paiement n'a pas été reconnu par le store. | | paymentNotAllowed | 4 |

Ce code d'erreur indique que l'utilisateur n'est pas autorisé à valider des paiements. Raisons possibles :

- Les paiements ne sont pas pris en charge dans le pays de l'utilisateur.

- L'utilisateur est mineur.

| | storeProductNotAvailable | 5 | Ce code d'erreur indique que le produit demandé est absent de l'App Store. Assurez-vous que le produit est disponible pour le pays utilisé. | | cloudServicePermissionDenied | 6 | Ce code d'erreur indique que l'utilisateur n'a pas autorisé l'accès aux informations du service Cloud. | | cloudServiceNetworkConnectionFailed | 7 | Ce code d'erreur indique que l'appareil n'a pas pu se connecter au réseau. | | cloudServiceRevoked | 8 | Ce code d'erreur indique que l'utilisateur a révoqué l'autorisation d'utiliser ce service cloud. | | privacyAcknowledgementRequired | 9 | Ce code d'erreur indique que l'utilisateur n'a pas encore accepté la politique de confidentialité du store. | | unauthorizedRequestData | 10 | Ce code d'erreur indique que la requête est mal construite. | | invalidOfferIdentifier | 11 |

L'identifiant de l'offre n'est pas valide. Raisons possibles :

- Vous n'avez pas configuré d'offre avec cet identifiant dans l'App Store.

- Vous avez révoqué l'offre.

- Vous avez mal saisi l'identifiant de l'offre.

| | invalidSignature | 12 | Ce code d'erreur indique que la signature dans une remise de paiement n'est pas valide. Assurez-vous d'avoir renseigné le champ **In-app purchase Key ID** et téléchargé le fichier **In-App Purchase Private Key**. Consultez la rubrique [Configure App Store integration](app-store-connection-configuration) pour plus de détails. | | missingOfferParams | 13 |

Cette erreur indique des problèmes avec l'intégration Adapty ou avec les offres.

Consultez [Configure App Store integration](app-store-connection-configuration) et [Offers](offers) pour savoir comment les configurer.

| | invalidOfferPrice | 14 | Ce code d'erreur indique que le prix que vous avez spécifié dans le store n'est plus valide. Les offres doivent toujours représenter un prix réduit. | ## Codes Android personnalisés \{#custom-android-codes\} | Erreur | Code | Description | |-----|----|-----------| | adaptyNotInitialized | 20 | Vous devez configurer correctement le SDK Adapty via la méthode `Adapty.activate`. Découvrez comment procéder [pour React Native](sdk-installation-reactnative). | | productNotFound | 22 | Cette erreur indique que le produit demandé à l'achat n'est pas disponible dans le store. | | invalidJson | 23 | Le JSON du paywall n'est pas valide. Corrigez-le dans l'Adapty Dashboard. Consultez la rubrique [Customize paywall with remote config](customize-paywall-with-remote-config) pour plus de détails. | | currentSubscriptionToUpdateNotFoundInHistory | 24 | L'abonnement d'origine à renouveler est introuvable. | | pendingPurchase | 25 | Cette erreur indique que l'état de l'achat est en attente plutôt qu'acheté. Consultez la page [Handling pending transactions](https://developer.android.com/google/play/billing/integrate#pending) dans la documentation Android Developer pour plus de détails. | | billingServiceTimeout | 97 | Cette erreur indique que la requête a atteint le délai d'expiration maximal avant que Google Play puisse répondre. Cela peut être causé, par exemple, par un retard dans l'exécution de l'action demandée par l'appel de la Play Billing Library. | | featureNotSupported | 98 | La fonctionnalité demandée n'est pas prise en charge par le Play Store sur l'appareil actuel. | | billingServiceDisconnected | 99 | Cette erreur fatale indique que la connexion de l'application cliente au service Google Play Store via le `BillingClient` a été interrompue. | | billingServiceUnavailable | 102 | Cette erreur temporaire indique que le service Google Play Billing est actuellement indisponible. Dans la plupart des cas, cela signifie qu'il y a un problème de connexion réseau entre l'appareil client et les services Google Play Billing. | | billingUnavailable | 103 |

Cette erreur indique qu'une erreur de facturation utilisateur s'est produite pendant le processus d'achat. Exemples de situations où cela peut se produire :

1\. L'application Play Store sur l'appareil de l'utilisateur est obsolète.

2. L'utilisateur se trouve dans un pays non pris en charge.

3. L'utilisateur est un utilisateur entreprise, et son administrateur a désactivé les achats pour les utilisateurs.

4. Google Play ne peut pas débiter le moyen de paiement de l'utilisateur. Par exemple, la carte de crédit de l'utilisateur a peut-être expiré.

5. L'utilisateur n'est pas connecté à l'application Play Store.

| | developerError | 105 | Il s'agit d'une erreur fatale indiquant que vous utilisez incorrectement une API. | | billingError | 106 | Il s'agit d'une erreur fatale indiquant un problème interne avec Google Play lui-même. | | itemAlreadyOwned | 107 | Le produit consommable a déjà été acheté. | | itemNotOwned | 108 | Cette erreur indique que l'action demandée sur l'élément a échoué car | ## Codes StoreKit personnalisés \{#custom-storekit-codes\} | Erreur | Code | Description | |-----|----|-----------| | noProductIDsFound | 1000 |

Cette erreur indique qu'aucun des produits du paywall n'est disponible dans le store.

Si vous rencontrez cette erreur, suivez les étapes ci-dessous pour la résoudre :

1. Vérifiez que tous les produits ont été ajoutés à l'Adapty Dashboard.

2. Assurez-vous que le Bundle ID de votre application correspond à celui d'Apple Connect.

3. Vérifiez que les identifiants de produits des stores correspondent à ceux que vous avez ajoutés au tableau de bord. Notez que les identifiants ne doivent pas contenir le Bundle ID, sauf s'il est déjà inclus dans le store.

4. Confirmez que le statut de paiement de l'application est actif dans vos paramètres fiscaux Apple. Assurez-vous que vos informations fiscales sont à jour et que vos certificats sont valides.

5. Vérifiez qu'un compte bancaire est associé à l'application afin qu'elle soit éligible à la monétisation.

6. Vérifiez si les produits sont disponibles dans toutes les régions. Assurez-vous également que vos produits sont à l'état **"Ready to Submit"**.

| | productRequestFailed | 1002 |

Impossible de récupérer les produits disponibles pour le moment. Raison possible :

- Aucun cache n'a encore été créé et il n'y a pas de connexion Internet simultanément.

| | cantMakePayments | 1003 | Les achats intégrés ne sont pas autorisés sur cet appareil. | | noPurchasesToRestore | 1004 | Cette erreur indique que Google Play n'a pas trouvé d'achat à restaurer. | | cantReadReceipt | 1005 |

Aucun reçu valide n'est disponible sur l'appareil. Cela peut poser problème lors des tests en sandbox.

Aucune action n'est requise, mais en termes de logique métier, vous pouvez proposer une remise à votre utilisateur ou lui rappeler plus tard.

| | productPurchaseFailed | 1006 | L'achat du produit a échoué. Cette erreur encapsule une erreur StoreKit sous-jacente — lisez l'erreur encapsulée (ou activez les logs détaillés pour la voir dans la console) pour connaître la raison réelle. L'erreur encapsulée est généralement l'un des codes StoreKit 0–14 du tableau ci-dessus — le plus souvent `paymentCancelled`, `paymentInvalid`, `paymentNotAllowed` ou `invalidOfferPrice`. Si vous ne pouvez pas identifier une raison précise, essayez un nouveau [profil sandbox](test-purchases-in-sandbox) ; si le problème persiste, contactez le support Apple. | | refreshReceiptFailed | 1010 | Cette erreur indique que le reçu n'a pas été reçu. Applicable à StoreKit 1 uniquement. | | receiveRestoredTransactionsFailed | 1011 | La restauration des achats a échoué. | ## Codes réseau personnalisés \{#custom-network-codes\} | Erreur | Code | Description | | :------------------- | :--- | :----------------------------------------------------------- | | notActivated | 2002 | Vous devez configurer correctement le SDK Adapty via la méthode `Adapty.activate`. Découvrez comment procéder [pour React Native](sdk-installation-reactnative). | | badRequest | 2003 | Requête incorrecte. | | serverError | 2004 | Erreur serveur. | | networkFailed | 2005 | La requête réseau a échoué. | | decodingFailed | 2006 | Cette erreur indique que le décodage de la réponse a échoué. | | encodingFailed | 2009 | Cette erreur indique que l'encodage de la requête a échoué. | | analyticsDisabled | 3000 | Nous ne pouvons pas traiter les événements analytics, car vous les avez désactivés. Consultez la rubrique [Analytics integration](analytics-integration) pour plus de détails. | | wrongParam | 3001 | Cette erreur indique que certains de vos paramètres sont incorrects : vide alors qu'il ne devrait pas l'être, mauvais type, etc. | | activateOnceError | 3005 | Il n'est pas possible d'appeler la méthode `.activate` plus d'une fois. | | profileWasChanged | 3006 | Le profil utilisateur a été modifié pendant l'opération. | | fetchTimeoutError | 3101 | Cette erreur signifie que le paywall n'a pas pu être récupéré dans le délai imparti. Pour éviter cette situation, [configurez des fallbacks locaux](fetch-paywalls-and-products). | | operationInterrupted | 9000 | Cette opération a été interrompue par le système. | --- # File: capacitor-sdk-migration-guides --- --- title: "Guides de migration pour le SDK Capacitor" description: "Guides de migration pour les versions du SDK Adapty Capacitor." --- Cette page regroupe tous les guides de migration pour le SDK Adapty Capacitor. Choisissez la version vers laquelle vous souhaitez migrer pour obtenir des instructions détaillées : - **[Migrer vers v4.0 (beta)](migration-to-capacitor-sdk-v4)** - [**Migrer vers v3.16**](migration-to-capacitor-316) --- # File: migration-to-capacitor-sdk-v4 --- --- title: "Migrer le SDK Adapty Capacitor vers la v. 4.0" description: "Migrez vers le SDK Adapty Capacitor v4.0 (bêta) en remplaçant les API paywall par des API flow, compatibles avec le Flow Builder et le Paywall Builder." --- Le SDK Adapty Capacitor 4.0 (bêta) introduit les flows et renomme les API paywall en conséquence. Les nouvelles API fonctionnent aussi bien avec le nouveau Flow Builder qu'avec le Paywall Builder existant — aucune modification de configuration n'est requise côté Adapty Dashboard. ## Référence rapide \{#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` (type) | `AdaptyFlow` + `AdaptyFlowPaywall` | | `createPaywallView(paywall, params?)` | `createFlowView(flow, params?)` | | `PaywallViewController` | `FlowViewController` | | `EventHandlers` (type) | `FlowEventHandlers` | | `CreatePaywallViewParamsInput` | `CreateFlowViewParamsInput` | | `onRenderingFailed` | `onError` | `AdaptyPaywallProduct` conserve son nom — les produits appartiennent toujours à un flow, et `getPaywallProducts` conserve également son nom, en prenant désormais un `AdaptyFlow`. Les méthodes `getFlow` et `getFlowForDefaultAudience` ne prennent plus de paramètre `locale` — passez-le plutôt à `createFlowView`. Les API d'achat et de profil (`makePurchase`, `restorePurchases`, `getProfile`, `identify`, `updateProfile`) et `setFallback` conservent les mêmes signatures, mais le fichier de secours lui-même doit être retéléchargé — voir [Fichiers de secours](#fallback-files). Les méthodes de vue `present`, `dismiss`, `setEventHandlers` et `showDialog`, ainsi que les gestionnaires d'événements `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` et `onAndroidSystemBack` conservent les mêmes noms qu'en v3. Les méthodes d'onboarding fonctionnent toujours mais sont dépréciées — voir [Dépréciation de l'API onboarding](#onboarding-api-deprecation). Certains comportements par défaut ont changé — voir [Changements de comportement par défaut](#default-behavior-changes). ## Versions minimales \{#minimum-versions\} Les prérequis d'exécution sont inchangés depuis v3.16+ : **iOS 15.0**, **Android minSdk 24** et **Capacitor 8**. Aucune modification de la cible de déploiement n'est nécessaire. Il y a un nouveau prérequis de build : **Xcode 26 ou supérieur** — le SDK iOS natif Adapty 4.0.2 inclus dans cette version utilise Swift tools 6.2. v4 intègre les SDK natifs Adapty iOS 4.0.2 et Android BOM 4.0.1. ## Installation \{#installation\} ### Mettre à jour le package La v4.0 est une version préliminaire, il faut donc épingler la version exacte — npm ne sélectionne pas les versions préliminaires avec les plages caret/tilde : ```bash showLineNumbers npm install @adapty/capacitor@4.0.1-beta.1 ``` Synchronisez ensuite les projets natifs : ```bash showLineNumbers npx cap sync ``` ### iOS : Swift Package Manager uniquement \{#ios-swift-package-manager-only\} [Le dépôt de specs CocoaPods passe en lecture seule en décembre 2026](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), donc à partir de la v4, le fichier `AdaptyCapacitor.podspec` est supprimé et le SDK s'installe sur iOS **uniquement via Swift Package Manager (SPM)**. Le projet iOS de votre application doit utiliser l'intégration SPM de Capacitor : - Nouvelles applications : ajoutez la plateforme iOS avec le gestionnaire de paquets SPM : ```bash showLineNumbers npx cap add ios --packagemanager SPM ``` - Applications existantes basées sur CocoaPods : migrez le projet iOS en suivant le [guide Capacitor pour utiliser SPM dans un projet existant](https://capacitorjs.com/docs/ios/spm#using-spm-in-an-existing-capacitor-project). Consultez [Installer le SDK Adapty](sdk-installation-capacitor) pour la configuration complète. ## Récupération des flows \{#fetching-flows\} ### getPaywall → getFlow Le type retourné passe de `AdaptyPaywall` à `AdaptyFlow`, et l'option `locale` quitte l'appel de récupération pour rejoindre `createFlowView` ; pour les paywalls personnalisés, toutes les locales sont retournées dans `flow.remoteConfigs` : ```diff showLineNumbers - const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en' }); + const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); + const view = await createFlowView(flow, { locale: 'en' }); ``` `locale` reste optionnel dans `createFlowView` : omettez-le et la vue s'affiche en `en`, ou dans la localisation par défaut du flow si celui-ci ne dispose pas de `en`. Voir [Localisations et codes de langue](capacitor-localizations-and-locale-codes). `getPaywallForDefaultAudience` est renommé de la même façon : ```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` conserve son nom mais accepte désormais un `AdaptyFlow` : ```diff showLineNumbers - const products = await adapty.getPaywallProducts({ paywall }); + const products = await adapty.getPaywallProducts({ flow }); ``` ### Fichiers de secours \{#fallback-files\} Le format du fichier de secours [a changé avec le SDK v4](fallback-flows). Téléchargez le nouveau fichier depuis **[Placements](https://app.adapty.io/placements)** > **Fallbacks** et intégrez-le dans votre application. ## Modèle de données \{#data-model\} `getFlow` retourne un `AdaptyFlow` au lieu d'un `AdaptyPaywall`, et la structure de l'objet a changé : | Champ v3 `AdaptyPaywall` | Champ v4 `AdaptyFlow` | Action | |---|---|---| | `remoteConfig?` (unique) | `remoteConfigs?: AdaptyRemoteConfig[]` (tableau) | Un flow porte un Remote Config par langue configurée. Lisez celui qui correspond à l'utilisateur : `flow.remoteConfigs?.find((c) => c.lang === 'en')`. | | `products` | `flow.paywalls[i].productIdentifiers` | Les identifiants de produits se trouvent désormais sur chaque variation du flow, et non sur le flow lui-même. | | `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Déplacé du flow vers chaque variation de paywall. | | `version?: number` | `flowVersionId?: string` | Renommé, et le type est passé de `number` à `string`. | | `hasViewConfiguration` | supprimé | Supprimez tout contrôle `hasViewConfiguration` de votre code — `createFlowView` lève désormais une exception à la place (voir [Affichage des flows](#displaying-flows)). | | `requestLocale` | supprimé | La langue ne fait plus partie du modèle. | | _(nouveau)_ | `paywalls: AdaptyFlowPaywall[]` | Chaque entrée correspond à une variation de paywall dans le flow. | | _(nouveau)_ | `responseCreatedAt: number` | Horodatage de la réponse du serveur, en millisecondes. | `hasViewConfiguration` et `requestLocale` restent sur `AdaptyOnboarding` — seul le modèle de flow les supprime. Les identifiants de produits ont été déplacés du flow vers chaque variante : ```diff showLineNumbers - const ids = paywall.products; + const ids = flow.paywalls[0].productIdentifiers; ``` ## Méthodes de paywall web \{#web-paywall-methods\} `openWebPaywall` et `createWebPaywallUrl` conservent leurs noms, mais l'option `paywallOrProduct` accepte désormais un `AdaptyFlowPaywall` (une variante de flow) plutôt qu'un `AdaptyPaywall`. Vous pouvez toujours passer un `AdaptyPaywallProduct`. Vérifiez que `flow.paywalls` n'est pas vide avant de lire la première entrée : ```diff showLineNumbers const flow = await adapty.getFlow({ placementId: 'YOUR_PLACEMENT_ID' }); - await adapty.openWebPaywall({ paywallOrProduct: paywall }); + await adapty.openWebPaywall({ paywallOrProduct: flow.paywalls[0] }); ``` ## Suivi des vues de flow \{#tracking-flow-views\} ### logShowPaywall → logShowFlow `logShowPaywall` est renommé en `logShowFlow` et prend désormais un `AdaptyFlow`. L'événement est toujours enregistré pour la même variation, donc les métriques de funnel et de test A/B existantes continuent de fonctionner sans modification du tableau de bord. ```diff showLineNumbers - await adapty.logShowPaywall({ paywall }); + await adapty.logShowFlow({ flow }); ``` Comme dans la v3, vous n'avez pas besoin d'appeler cette méthode lors de l'affichage de flows ou de paywalls rendus par le [Flow Builder](adapty-flow-builder) ou le [Paywall Builder](adapty-paywall-builder) — Adapty suit ces vues automatiquement. ## Affichage des flows \{#displaying-flows\} ### createPaywallView → createFlowView Renommez la fonction factory et passez l'`AdaptyFlow`. Le contrôleur retourné est renommé de `PaywallViewController` en `FlowViewController`, mais ses méthodes (`present`, `dismiss`, `setEventHandlers`, `showDialog`) restent inchangées. Le type des paramètres est renommé de `CreatePaywallViewParamsInput` en `CreateFlowViewParamsInput` : ```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` lève une `AdaptyError` si le flow n'a pas de vue configurée — ce qui remplace la vérification `hasViewConfiguration` de la v3 : ```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 Une vue de flow est à usage unique : après avoir appelé `dismiss()`, la vue est détruite et ses gestionnaires d'événements sont effacés. Appelez à nouveau `createFlowView` pour afficher le flow une nouvelle fois. ::: ### Marges de zone sécurisée Android \{#android-safe-area-paddings\} `CreateFlowViewParamsInput` ajoute un nouveau paramètre : `enableSafeArea`, qui contrôle les marges de zone sécurisée Android à l'exécution. Il est imbriqué sous la clé `android` et vaut `true` par défaut : ```typescript showLineNumbers const view = await createFlowView(flow, { android: { enableSafeArea: true }, }); ``` ## Gestion des événements \{#handling-events\} L'interface du gestionnaire d'événements est renommée de `EventHandlers` en `FlowEventHandlers`, et un callback est renommé. Les corps des gestionnaires existants n'ont pas besoin d'être modifiés — il suffit de renommer : ```diff showLineNumbers - onRenderingFailed: (error) => { /* … */ }, + onError: (error) => { /* … */ }, ``` Tous les autres gestionnaires d'événements conservent leur nom. Deux d'entre eux reçoivent également un deuxième argument : `onPurchaseCompleted` devient `(purchaseResult, product)` et `onPurchaseFailed` devient `(error, product)`, où `product` est l'`AdaptyPaywallProduct` concerné. Consultez [Gérer les événements de flow et de paywall](capacitor-handling-events) pour la liste complète. v4 ajoute également quelques fonctionnalités que vous pouvez activer : - Les méthodes `adapty.openWebUrl({ url, openIn })` et `adapty.requestAppReview()` — elles alimentent les gestionnaires par défaut `onUrlPress` et `onRequestAppReview`, de sorte que les URLs et les demandes d'évaluation de l'application sont gérées nativement sans configuration particulière. Ne les appelez directement que si vous remplacez ces gestionnaires. - Gestion des achats en mode Observateur dans les flows via les nouveaux gestionnaires `onObserverPurchaseInitiated` / `onObserverRestoreInitiated`. Voir [Présenter des flows en mode Observateur](capacitor-present-flows-in-observer-mode). ## Changements de comportement par défaut \{#default-behavior-changes\} Ces changements ne provoquent pas d'erreurs de compilation, testez-les donc à l'exécution : - **`onAndroidSystemBack`**: Le comportement par défaut est passé de la fermeture de la vue à son maintien ouvert. Pour retrouver l'ancien comportement, renvoyez `true` depuis le handler. - **`onPurchaseCompleted`**: Le comportement par défaut est passé de la fermeture de la vue (sauf si l'utilisateur a annulé l'achat) à son maintien ouvert dans tous les cas. Pour retrouver l'ancien comportement, renvoyez `purchaseResult.type !== 'user_cancelled'` depuis le handler. - **`onRestoreCompleted`**: Le comportement par défaut est passé de la fermeture de la vue après une restauration réussie à son maintien ouvert. Pour retrouver l'ancien comportement, renvoyez `true` depuis le handler. - **`onUrlPress`**: Le comportement par défaut ouvre désormais l'URL via la couche native, en respectant le paramètre de navigateur intégré ou externe configuré dans le tableau de bord. Surchargez le handler pour ouvrir les URL vous-même. - **Les vues sont à usage unique** : après `dismiss()`, la vue est détruite. Appelez `createFlowView` à nouveau pour afficher le flow une nouvelle fois. ## API supprimées \{#removed-apis\} ### Exports supprimés Ces symboles ne sont plus exportés depuis `@adapty/capacitor`. Supprimez leurs imports : - **`AdaptyPaywall`** : Utilisez `AdaptyFlow` et `AdaptyFlowPaywall` à la place. - **`ProductReference`** : Utilisez `AdaptyProductIdentifier`, accessible via `flow.paywalls[i].productIdentifiers`. - **`AdaptyPaywallBuilder`** : Supprimé. Les flows et paywalls s'affichent nativement. - **`AdaptyAndroidSubscriptionUpdateParameters`** : Utilisez la structure imbriquée des paramètres d'achat `android` (voir ci-dessous). ### activate: lockMethodsUntilReady `lockMethodsUntilReady` (déjà obsolète et sans effet en v3) est supprimé. Retirez-le de votre appel `activate` — le conserver ne compile plus : ```diff showLineNumbers - await adapty.activate({ apiKey: 'PUBLIC_SDK_KEY', params: { lockMethodsUntilReady: true } }); + await adapty.activate({ apiKey: 'PUBLIC_SDK_KEY' }); ``` ### makePurchase : paramètres Android \{#makepurchase-android-parameters\} La forme Android plate (deprecated) de `MakePurchaseParamsInput` est supprimée — seule la forme imbriquée subsiste. Déplacez les paramètres d'achat Android dans `params: { android: { ... } }`. Consultez [Effectuer des achats](capacitor-making-purchases) pour un exemple complet. ## Dépréciation de l'API onboarding \{#onboarding-api-deprecation\} L'ancienne API onboarding est dépréciée depuis la v4.0 au profit du [Flow Builder](adapty-flow-builder). Elle fonctionne toujours, mais sera supprimée dans une future version — prévoyez donc la migration de vos onboardings vers le Flow Builder. Symboles dépréciés : `getOnboarding`, `getOnboardingForDefaultAudience`, `createOnboardingView` et `OnboardingViewController`. --- # File: migration-to-capacitor-316 --- --- title: "Migrer le SDK Adapty Capacitor vers v3.16" description: "Migrez vers le SDK Adapty Capacitor v3.16 pour de meilleures performances et de nouvelles fonctionnalités de monétisation." --- À partir de la version 3.16.0 du SDK Adapty, Capacitor 8 est requis. Si vous avez besoin de Capacitor 7, utilisez la version 3.15 du SDK Adapty. Pour passer au SDK Capacitor v3.16, assurez-vous que votre projet utilise Capacitor 8. Si vous utilisez encore Capacitor 7, deux options s'offrent à vous : 1. **Passer à Capacitor 8** : Suivez le [guide officiel de migration Capacitor](https://capacitorjs.com/docs/updating/8-0) pour mettre à jour votre projet, puis installez le SDK Adapty v3.16. 2. **Rester sur le SDK Adapty v3.15** : Si la mise à niveau vers Capacitor 8 n'est pas envisageable, continuez à utiliser le SDK Adapty v3.15, qui prend en charge Capacitor 7. --- # End of Documentation _Generated on: 2026-08-04T15:08:25.967Z_ _Successfully processed: 45/45 files_