# REACT-NATIVE - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ru Generated on: 2026-07-24T13:01:12.810Z Total files: 45 --- # File: sdk-installation-react-native-expo --- --- title: "Install & configure Adapty React Native SDK in an Expo project" description: "Step-by-step guide on installing Adapty React Native SDK in an Expo project for subscription-based apps." --- :::important Этот гайд охватывает установку и настройку Adapty SDK для React Native **в проекте Expo**. Если вы используете **чистый React Native (без Expo)**, следуйте [гайду по установке для React Native](sdk-installation-react-native-pure). ::: Adapty SDK включает два ключевых модуля для интеграции в ваше React Native приложение: - **Core Adapty**: Этот модуль необходим для корректной работы Adapty в вашем приложении. - **AdaptyUI**: Этот модуль нужен, если вы используете [Adapty Paywall Builder](adapty-paywall-builder) — удобный инструмент без кода для создания кроссплатформенных пейволов. AdaptyUI активируется автоматически вместе с основным модулем. Если вам нужен полный туториал по реализации встроенных покупок в React Native-приложении, ознакомьтесь с [этим материалом](https://adapty.io/blog/react-native-in-app-purchases-tutorial/). :::tip Хотите увидеть реальный пример интеграции Adapty SDK в Expo-приложение? Посмотрите наши примеры: - [Пример Expo dev build](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) — полная функциональность, включая реальные покупки и Paywall Builder - [Пример Expo Go & Web](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) — тестирование в режиме мока ::: Полное пошаговое руководство по реализации также доступно в виде видео:
### В процессе входа/регистрации \{#during-loginsignup\}
Если вы идентифицируете пользователей после запуска приложения (например, после входа в аккаунт или регистрации), используйте метод `identify`, чтобы задать их customer user ID.
- Если вы **не использовали этот customer user ID раньше**, Adapty автоматически свяжет его с текущим профилем.
- Если вы **уже использовали этот customer user ID для идентификации пользователя**, Adapty переключится на работу с профилем, связанным с этим customer user ID.
:::important
Идентификаторы пользователей должны быть уникальными для каждого пользователя. Если захардкодить значение параметра, все пользователи будут считаться одним.
:::
Всегда используйте `await` для `identify` перед вызовом других методов SDK. Параллельные вызовы приводят к ошибке `#3006 profileWasChanged` или работают с анонимным профилем. См. [Порядок вызовов в React Native SDK](react-native-sdk-call-order).
```typescript showLineNumbers
try {
await adapty.identify("YOUR_USER_ID"); // Unique for each user
// successfully identified
} catch (error) {
// handle the error
}
```
### При активации SDK \{#during-the-sdk-activation\}
Если вы знаете customer user ID ещё до активации SDK, его можно передать прямо в метод `activate` — и не вызывать `identify` отдельно.
Если же вы знаете customer user ID, но устанавливаете его только после активации, то при активации Adapty создаст новый анонимный профиль и переключится на существующий лишь после вызова `identify`.
Вы можете передать как существующий customer user ID (который вы уже использовали ранее), так и новый. Если передать новый, профиль, созданный при активации, будет автоматически привязан к этому customer user ID.
:::note
По умолчанию создание анонимных профилей не влияет на аналитические дашборды, поскольку установки считаются на основе идентификаторов устройств.
Идентификатор устройства соответствует одной установке приложения из стора и обновляется только при переустановке приложения.
Он не зависит от того, является ли установка первой или повторной, а также от того, используется ли существующий пользовательский ID.
Создание профиля (при активации SDK или выходе из системы), вход в систему или обновление приложения без его переустановки не генерируют дополнительных событий установки.
Если вы хотите считать установки на основе уникальных пользователей, а не устройств, перейдите в **App settings** и настройте [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```typescript showLineNumbers
adapty.activate("PUBLIC_SDK_KEY", {
customerUserId: "YOUR_USER_ID" // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
});
```
### Выход пользователей из аккаунта \{#log-users-out\}
Если в приложении есть кнопка выхода, используйте метод `logout`.
:::important
Выход из аккаунта создаёт новый анонимный профиль для пользователя.
:::
```typescript showLineNumbers
try {
await adapty.logout();
// successful logout
} catch (error) {
// handle the error
}
```
:::info
Чтобы снова войти в аккаунт, используйте метод `identify`.
:::
### Разрешите покупки без входа в систему \{#allow-purchases-without-login\}
Если пользователи могут совершать покупки как до, так и после входа в приложение, необходимо убедиться, что после входа они сохранят доступ:
1. Когда неавторизованный пользователь совершает покупку, Adapty привязывает её к анонимному ID профиля.
2. Когда пользователь входит в аккаунт, Adapty переключается на работу с идентифицированным профилем.
- Если это новый customer user ID (например, покупка была совершена до регистрации), Adapty присваивает customer user ID текущему профилю, сохраняя всю историю покупок.
- Если customer user ID уже существует (он уже привязан к профилю), после переключения профиля нужно получить актуальный уровень доступа. Для этого можно вызвать [`getProfile`](react-native-check-subscription-status) сразу после идентификации или [подписаться на обновления профиля](react-native-check-subscription-status), чтобы данные синхронизировались автоматически.
## Следующие шаги \{#next-steps\}
Поздравляем! Вы реализовали логику встроенных покупок в своём приложении! Желаем вам всего наилучшего в монетизации вашего приложения!
Чтобы получить от Adapty ещё больше, изучите эти темы:
- [**Тестирование**](troubleshooting-test-purchases): Убедитесь, что всё работает как ожидается
- [**Онбординги**](react-native-onboardings): Вовлекайте пользователей с помощью онбордингов и повышайте удержание
- [**Интеграции**](configuration): Интегрируйтесь с сервисами маркетинговой атрибуции и аналитики буквально в одну строку кода
- [**Настройка атрибутов профиля**](react-native-setting-user-attributes): Добавляйте пользовательские атрибуты к профилям и создавайте сегменты — чтобы запускать A/B-тесты или показывать разные пейволы разным пользователям
---
# File: adapty-sdk-integration-skill-react-native
---
---
title: "Интеграция Adapty в приложение React Native с помощью навыка SDK integration"
description: "Используйте навык adapty-sdk-integration для сквозной интеграции Adapty SDK в приложение React Native с помощью вашего AI-инструмента для кодирования."
---
[Скилл adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) автоматизирует интеграцию Adapty от начала до конца: настройку дашборда, установку SDK, пейвол и проверку на каждом этапе. Он автоматически определяет вашу платформу и подгружает нужную документацию Adapty на каждом шаге.
**Поддерживаемые инструменты**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Для установки выберите команду для своего инструмента. Полный список — в [README скилла](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 или любой другой инструмент** — используйте [skills CLI](https://skills.sh) (обратите внимание, что скиллы, установленные таким способом, не обновляются автоматически):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
Либо клонируйте репозиторий и скопируйте `skills/adapty-sdk-integration/` в директорию скиллов вашего инструмента.
После установки запустите скилл в вашем проекте:
```
/adapty-sdk-integration
```
Скилл задаст несколько вопросов по настройке, а затем проведёт через настройку дашборда, установку SDK, пейвол и проверку.
:::important
Этот навык находится в бета-версии. Если он зависает или ведёт себя непредсказуемо, воспользуйтесь [пошаговым руководством по интеграции](adapty-cursor-react-native) — оно проведёт ваш AI-инструмент через каждый этап с нужной документацией.
:::
[Скилл adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) автоматизирует интеграцию Adapty от начала до конца: настройку дашборда, установку SDK, пейвол и проверку на каждом этапе. Он автоматически определяет вашу платформу и подгружает нужную документацию Adapty на каждом шаге.
**Поддерживаемые инструменты**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Для установки выберите команду для своего инструмента. Полный список — в [README скилла](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 или любой другой инструмент** — используйте [skills CLI](https://skills.sh) (обратите внимание, что скиллы, установленные таким способом, не обновляются автоматически):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
Либо клонируйте репозиторий и скопируйте `skills/adapty-sdk-integration/` в директорию скиллов вашего инструмента.
После установки запустите скилл в вашем проекте:
```
/adapty-sdk-integration
```
Скилл задаст несколько вопросов по настройке, а затем проведёт через настройку дашборда, установку SDK, пейвол и проверку.
---
# File: adapty-cursor-react-native
---
---
title: "Интеграция Adapty в ваше React Native приложение с помощью ИИ"
description: "Пошаговое руководство по интеграции Adapty в ваше React Native приложение с использованием Cursor, Context7, ChatGPT, Claude или других ИИ-инструментов."
---
Это руководство шаг за шагом проведёт вас через интеграцию Adapty в ваше приложение на React Native с помощью AI-инструмента для написания кода — вы даёте ему нужную документацию Adapty в правильном порядке.
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.
## Прежде чем начать: настройка дашборда \{#before-you-start-dashboard-setup\}
Adapty требует предварительной настройки в дашборде — до того как вы начнёте писать код с использованием SDK. Это можно сделать с помощью интерактивного LLM-скилла или вручную через дашборд.
### Подход через skill (рекомендуется) \{#skill-approach-recommended\}
Skill Adapty CLI позволяет вашему LLM настраивать приложение, продукты, уровни доступа, пейволы и плейсменты напрямую — без необходимости открывать дашборд на каждом шаге. Нужно только [подключить сторы](integrate-payments) в дашборде.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
После добавления skill запустите `/adapty-cli` в своём агенте. Он проведёт вас через каждый шаг — включая момент, когда нужно открыть дашборд для подключения сторов.
### Подход через дашборд
Если вы предпочитаете настраивать всё вручную, вот что нужно сделать до написания кода. Ваш LLM не может самостоятельно получить значения из дашборда — вам придётся предоставить их самостоятельно.
1. **Подключите сторы**: В дашборде Adapty перейдите в **App settings → General**. Подключите App Store и Google Play, если ваше приложение поддерживает обе платформы. Это обязательное условие для работы покупок.
[Подключите сторы](integrate-payments)
2. **Скопируйте публичный SDK-ключ**: В дашборде Adapty перейдите в **App settings → General** и найдите раздел **API keys**. В коде это строка, которую вы передаёте в `adapty.activate("YOUR_PUBLIC_SDK_KEY")`.
3. **Создайте хотя бы один продукт**: В дашборде Adapty перейдите на страницу **Products**. В коде ссылаться на продукты напрямую не нужно — Adapty передаёт их через пейволы.
[Добавить продукты](quickstart-products)
4. **Создайте пейвол и плейсмент**: В дашборде Adapty создайте пейвол на странице **Paywalls**, затем привяжите его к плейсменту на странице **Placements**. В коде идентификатор плейсмента — это строка, которую вы передаёте в `adapty.getPaywall("YOUR_PLACEMENT_ID")`.
[Создать пейвол](quickstart-paywalls)
5. **Настройте уровни доступа**: в дашборде Adapty настройте каждый продукт на странице **Products**. В коде проверяйте строку `profile.accessLevels['premium']?.isActive`. Уровень доступа `premium` по умолчанию подходит большинству приложений. Если платящие пользователи получают доступ к разным функциям в зависимости от продукта (например, план `basic` и план `pro`), [создайте дополнительные уровни доступа](assigning-access-level-to-a-product) до начала разработки.
:::tip
Как только у вас есть все пять — можно писать код. Скажите LLM: «Мой публичный SDK-ключ — X, мой идентификатор плейсмента — Y», чтобы она сгенерировала правильный код инициализации и получения пейвола.
:::
### Настройте по мере готовности \{#set-up-when-ready\}
Это не обязательно для начала разработки, но пригодится по мере развития интеграции:
- **A/B-тесты**: настраиваются на странице **Placements**. Изменений в коде не требуется.
[A/B-тесты](ab-tests)
- **Дополнительные пейволы и плейсменты**: добавьте больше вызовов `getPaywall` с разными идентификаторами плейсментов.
- **Интеграции с аналитикой**: настраиваются на странице **Integrations**. Процесс настройки зависит от конкретной интеграции. См. [интеграции с аналитикой](analytics-integration) и [интеграции с атрибуцией](attribution-integration).
## Загрузите документацию Adapty в свой LLM \{#feed-adapty-docs-to-your-llm\}
### Используйте Context7 (рекомендуется) \{#use-context7-recommended\}
[Context7](https://context7.com) — это MCP-сервер, который даёт вашей LLM прямой доступ к актуальной документации Adapty. LLM автоматически находит нужные доки, исходя из вашего запроса, — никакого ручного копирования ссылок.
Context7 работает с **Cursor**, **Claude Code**, **Windsurf** и другими MCP-совместимыми инструментами. Для настройки выполните:
```
npx ctx7 setup
```
Команда определит ваш редактор и настроит сервер Context7. Для ручной настройки см. [репозиторий Context7 на GitHub](https://github.com/upstash/context7).
После настройки обращайтесь к библиотеке Adapty в своих промптах:
```
Use the adaptyteam/adapty-docs library to look up how to install the React Native SDK
```
:::warning
Несмотря на то что Context7 избавляет от необходимости вручную вставлять ссылки на документацию, порядок реализации важен. Следуйте [пошаговому руководству](#implementation-walkthrough) ниже строго по шагам, чтобы всё работало корректно.
:::
### Используйте документацию в формате обычного текста \{#use-plain-text-docs\}
Любой документ Adapty доступен в формате Markdown. Добавьте `.md` в конец URL или нажмите **Copy for LLM** под заголовком статьи. Например: [adapty-cursor-react-native.md](https://adapty.io/docs/ru/adapty-cursor-react-native.md).
Каждый шаг [пошагового руководства по интеграции](#implementation-walkthrough) ниже содержит блок «Отправьте это своему LLM» со ссылками `.md` для вставки.
Чтобы получить сразу несколько документов, смотрите [индексные файлы и подборки по платформам](#plain-text-doc-index-files) ниже.
## Пошаговое руководство по интеграции \{#implementation-walkthrough\}
Этот гайд проведёт вас через интеграцию Adapty в порядке реализации. Каждый этап включает документацию для передачи в LLM, описание ожидаемого результата и типичные проблемы.
### Планирование интеграции \{#plan-your-integration\}
Прежде чем браться за код, попросите LLM проанализировать ваш проект и составить план реализации. Если ваш AI-инструмент поддерживает режим планирования (например, Cursor или Claude Code), используйте его — тогда LLM сможет изучить структуру вашего проекта и документацию Adapty ещё до написания кода.
Укажите LLM, какой подход к покупкам вы используете — от этого зависит, какие гайды ей нужно будет применять:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Вы создаёте пейволы в визуальном редакторе Adapty, а SDK отображает их автоматически.
- [**Пейволы, созданные вручную**](react-native-making-purchases): Вы строите собственный интерфейс пейвола в коде, но используете Adapty для получения продуктов и обработки покупок.
- [**Режим наблюдателя**](observer-vs-full-mode): Вы сохраняете существующую инфраструктуру покупок и используете Adapty только для аналитики и интеграций.
Не знаете, что выбрать? Прочитайте [сравнительную таблицу в руководстве по быстрому старту](react-native-quickstart-paywalls).
### Установка и настройка SDK \{#install-and-configure-the-sdk\}
Добавьте зависимость Adapty SDK через npm (или yarn) и активируйте её с помощью вашего публичного ключа SDK. Это основа — без неё ничего не работает.
У нас есть отдельные гайды по установке для проектов на Expo и bare React Native — выберите тот, что подходит для вашего случая.
**Гайды:**
- [Установка с Expo](sdk-installation-react-native-expo)
- [Установка с bare React Native](sdk-installation-react-native-pure)
:::tip[Checkpoint]
- **Ожидаемый результат:** Приложение собирается и запускается на iOS и Android. В логах Metro bundler видна запись об активации Adapty.
- **Частая ошибка:** "Public API key is missing" → убедитесь, что заменили заглушку на реальный ключ из **App settings**.
:::
### Показ пейволов и обработка покупок \{#show-paywalls-and-handle-purchases\}
Получите пейвол по идентификатору плейсмента, отобразите его и обработайте события покупок. Нужные вам гайды зависят от того, как вы обрабатываете покупки.
Тестируйте каждую покупку в песочнице по ходу работы — не откладывайте на конец. Инструкции по настройке смотрите в разделе [Тестирование покупок в песочнице](test-purchases-in-sandbox).
По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае ошибки. Рекомендуем этот вариант — он гарантирует, что пользователи всегда получают самые актуальные данные.
Однако если у ваших пользователей нестабильный интернет, рассмотрите использование `.returnCacheDataElseLoad` — оно возвращает кешированные данные, если они есть. В этом случае пользователи могут не получить самые последние данные, зато время загрузки будет меньше независимо от качества соединения. Кеш обновляется регулярно, поэтому его безопасно использовать в рамках сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при переустановке или ручной очистке.
Adapty SDK хранит пейволы локально на двух уровнях: регулярно обновляемый кеш, описанный выше, и [резервные пейволы](fallback-paywalls). Для более быстрой загрузки пейволов мы также используем CDN и отдельный резервный сервер на случай недоступности CDN. Эта система обеспечивает получение актуальных версий пейволов и надёжную работу даже при слабом интернет-соединении.
| | **loadTimeoutMs** | по умолчанию: 5 сек |Это значение ограничивает таймаут для данного метода. По истечении таймаута будут возвращены кешированные данные или локальный резервный вариант.
Обратите внимание: в редких случаях метод может завершиться по таймауту немного позже, чем указано в `loadTimeout`, поскольку операция может состоять из нескольких запросов под капотом.
Для Android: можно создать `TimeInterval` с помощью функций-расширений (например, `5.seconds`, где `.seconds` — из `import com.adapty.utils.seconds`) или `TimeInterval.seconds(5)`. Чтобы убрать ограничение, используйте `TimeInterval.INFINITE`.
| Response parameters: | Параметр | Описание | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Объект `AdaptyFlow` с идентификаторами флоу (`id`, `variationId`), названием, плейсментом, вариантами пейвола (`paywalls`) и Remote Config (`remoteConfigs`). | ## Получение конфигурации представления \{#fetch-the-view-configuration\} :::important Убедитесь, что в билдере включён переключатель **Show on device**. Если этот параметр не включён, конфигурация представления не будет доступна для получения. ::: Если плейсмент был создан в **Flow Builder** или **Paywall Builder**, Adapty отрисовывает UI самостоятельно. Создайте представление с помощью `createFlowView`, затем [отобразите флоу или пейвол](react-native-present-paywalls). Если плейсмент — это кастомный пейвол без UI билдера, [обрабатывайте его как пейвол с Remote Config](present-remote-config-paywalls-react-native). В React Native SDK вызывайте `createFlowView` напрямую — предварительно получать конфигурацию не нужно. :::warning Результат метода `createFlowView` можно использовать только один раз. Если вам нужно использовать его повторно, вызовите метод `createFlowView` заново. Повторный вызов без пересоздания может привести к ошибке `AdaptyUIError.viewAlreadyPresented`. ::: ```typescript showLineNumbers try { const view = await createFlowView(flow); } catch (error) { // handle the error } ``` Параметры: | Параметр | Наличие | Описание | | :------------------- | :------- | :----------------------------------------------------------- | | **flow** | обязательный | Объект `AdaptyFlow` для получения контроллера нужного флоу/пейвола. | | **customTags** | необязательный | Словарь кастомных тегов и их значений. Кастомные теги служат плейсхолдерами в контенте и динамически заменяются на конкретные строки для персонализации контента во флоу/пейволе. Подробнее см. в разделе «Кастомные теги в Paywall Builder». | | **prefetchProducts** | необязательный | Включите для оптимизации времени отображения продуктов на экране. При значении `true` AdaptyUI автоматически загружает необходимые продукты. По умолчанию: `false`. | | **android.enableSafeArea** | необязательный | Только для Android (игнорируется на iOS). Передаётся как вложенный объект: `android: { enableSafeArea: true }`. При значении `true` к представлению флоу применяются отступы для безопасной области. По умолчанию `true` для модального представления (`createFlowView` + `present()`) и `false` для встраиваемого компонента `AdaptyFlowView`. Значение по умолчанию подходит для большинства случаев. | :::note Если вы используете несколько языков, узнайте, как добавить [локализацию флоу](add-paywall-locale-in-adapty-paywall-builder) и как правильно использовать коды локалей [здесь](react-native-localizations-and-locale-codes). ::: Когда у вас есть представление, [откройте флоу/пейвол](react-native-present-paywalls). ## Получение флоу или пейвола для аудитории по умолчанию для более быстрой загрузки \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Как правило, флоу и пейволы загружаются почти мгновенно, поэтому беспокоиться об ускорении этого процесса не нужно. Однако если у вас много аудиторий и плейсментов, а у пользователей слабое интернет-соединение, загрузка флоу или пейвола может занять больше времени, чем хотелось бы. В таких случаях можно показывать флоу или пейвол для аудитории по умолчанию — это обеспечит плавный пользовательский опыт вместо пустого экрана. Чтобы решить эту задачу, можно использовать метод `getFlowForDefaultAudience`, который получает флоу или пейвол указанного плейсмента для аудитории **All Users**. Однако важно понимать, что рекомендуемый подход — получать флоу или пейвол через метод `getFlow`, как описано в разделе [Получение флоу/пейвола](#fetch-flowpaywall) выше. :::warning Почему мы рекомендуем использовать `getFlow` Метод `getFlowForDefaultAudience` имеет ряд существенных недостатков: - **Потенциальные проблемы с обратной совместимостью**: если вам нужно показывать разные пейволы для разных версий приложения (текущей и будущих), вы можете столкнуться с трудностями. Придётся либо проектировать пейволы с поддержкой текущей (устаревшей) версии, либо мириться с тем, что пользователи этой версии могут видеть нерендерящиеся пейволы. - **Потеря таргетинга**: все пользователи будут видеть один и тот же пейвол, настроенный для аудитории **All Users**, что означает отказ от персонализированного таргетинга (в том числе по странам, маркетинговой атрибуции или собственным пользовательским атрибутам). Если вы готовы принять эти недостатки ради более быстрой загрузки флоу или пейвола, используйте метод `getFlowForDefaultAudience` следующим образом. В противном случае используйте `getFlow`, описанный [выше](#fetch-flowpaywall). ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlowForDefaultAudience(id); // the requested flow/paywall } catch (error) { // handle the error } ``` | Параметр | Наличие | Описание | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | обязательный | Идентификатор [плейсмента](placements). Это значение вы указали при создании плейсмента в дашборде Adapty. | | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае ошибки. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают самые актуальные данные.
Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование `.returnCacheDataElseLoad` — оно вернёт кешированные данные, если они есть. В этом случае пользователи могут получить не самые свежие данные, зато загрузка будет быстрее вне зависимости от качества связи. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы сократить количество сетевых запросов.
Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при его переустановке или принудительной очистке вручную.
| ## Кастомизация ресурсов \{#customize-assets\} Чтобы кастомизировать изображения и видео в своём флоу или пейволе, используйте пользовательские ресурсы. У hero-изображений и видео есть предопределённые ID: `hero_image` и `hero_video`. В пользовательском наборе ресурсов вы обращаетесь к этим элементам по их ID и настраиваете их поведение. Для остальных изображений и видео нужно [задать пользовательский ID](custom-media) в дашборде Adapty. Например, вы можете: - Показывать разные изображения или видео разным пользователям. - Показывать локальное превью, пока загружается основное удалённое изображение. - Показывать превью перед запуском видео. :::important Чтобы использовать эту функцию, обновите Adapty React Native SDK до версии 3.8.0 или выше. ::: Вот пример того, как можно передать кастомные ресурсы через простой словарь: ```javascript const customAssets: Recordнеобязательный
по умолчанию: `en`
|Идентификатор [локализации пейвола](add-paywall-locale-in-adapty-paywall-builder). Ожидается языковой код из одного или двух подтегов, разделённых дефисом (**-**). Первый подтег — язык, второй — регион.
Пример: `en` — английский, `pt-br` — бразильский португальский.
Подробнее о кодах локализации и рекомендациях по их использованию — в разделе [Локализации и коды локалей](localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера, а при ошибке возвращает кешированные данные. Мы рекомендуем именно этот вариант: он гарантирует, что пользователи всегда получают актуальные данные.
Если вы считаете, что ваши пользователи часто сталкиваются с нестабильным интернетом, рассмотрите `.returnCacheDataElseLoad` — возвращает кеш, если он есть. В этом случае данные могут быть не самыми свежими, зато загрузка будет быстрее при любом качестве соединения. Кеш обновляется регулярно, поэтому использовать его в течение сессии безопасно — это позволяет избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется между перезапусками приложения и очищается только при переустановке или вручную.
Adapty SDK хранит пейволы локально на двух уровнях: регулярно обновляемый кеш (описан выше) и [резервные пейволы](fallback-paywalls). Для быстрой загрузки используется CDN, а при его недоступности — отдельный резервный сервер. Такая система гарантирует, что вы всегда получаете актуальную версию пейволов, даже при нестабильном интернете.
| | **loadTimeoutMs** | по умолчанию: 5 сек |Ограничивает таймаут этого метода. По истечении таймаута возвращаются кешированные данные или локальный фолбэк.
Обратите внимание: в редких случаях метод может завершиться чуть позже указанного в `loadTimeout` значения, так как операция может включать несколько запросов под капотом.
Для Android: `TimeInterval` можно создать с помощью функций-расширений (например, `5.seconds`, где `.seconds` — из `import com.adapty.utils.seconds`) или `TimeInterval.seconds(5)`. Чтобы снять ограничение, используйте `TimeInterval.INFINITE`.
| ## Параметры ответа \{#response-parameters\} | Параметр | Описание | | :-------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Объект [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) со списком ID продуктов, идентификатором пейвола, Remote Config и рядом других свойств. | ## Получение конфигурации отображения пейвола, созданного в Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Убедитесь, что в Paywall Builder включён переключатель **Show on device**. Если он не активирован, конфигурация отображения не будет доступна для получения. ::: После получения пейвола проверьте, содержит ли он `ViewConfiguration` — это означает, что пейвол был создан в Paywall Builder. Это подскажет вам, как отображать пейвол. Если `ViewConfiguration` присутствует, обработайте его как пейвол Paywall Builder; если нет, [обработайте его как пейвол Remote Config](present-remote-config-paywalls-react-native). В React Native SDK напрямую вызовите метод `createPaywallView`, не получая предварительно конфигурацию представления вручную. :::warning Результат метода `createPaywallView` можно использовать только один раз. Если он нужен повторно, вызовите метод `createPaywallView` заново. Повторный вызов без пересоздания может привести к ошибке `AdaptyUIError.viewAlreadyPresented`. ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createPaywallView} from 'react-native-adapty/dist/ui'; if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { //use your custom logic } ``` Параметры: | Параметр | Обязательность | Описание | | :------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | обязательный | Объект `AdaptyPaywall` для получения контроллера нужного пейвола. | | **customTags** | необязательный | Словарь пользовательских тегов и их значений. Пользовательские теги служат плейсхолдерами в содержимом пейвола и динамически заменяются конкретными строками для персонализации контента. Подробнее см. в разделе о пользовательских тегах в Paywall Builder. | | **prefetchProducts** | необязательный | Включите для оптимизации времени отображения продуктов на экране. При значении `true` AdaptyUI автоматически загрузит необходимые продукты. По умолчанию: `false`. | :::note Если вы используете несколько языков, узнайте, как добавить [локализацию Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) и как правильно использовать коды локалей [здесь](react-native-localizations-and-locale-codes). ::: Получив объект представления, [покажите пейвол](react-native-present-paywalls). ## Получите пейвол для аудитории по умолчанию, чтобы загрузить его быстрее \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Как правило, пейволы загружаются почти мгновенно, и беспокоиться об ускорении этого процесса не нужно. Однако если у вас много аудиторий и пейволов, а у пользователей слабое интернет-соединение, загрузка пейвола может занять больше времени, чем хотелось бы. В таких ситуациях имеет смысл показывать пейвол по умолчанию — это обеспечит плавный пользовательский опыт вместо полного отсутствия пейвола. Чтобы решить эту задачу, используйте метод `getPaywallForDefaultAudience`, который получает пейвол указанного плейсмента для аудитории **All Users**. Однако важно понимать, что рекомендуемый подход — получать пейвол через метод `getPaywall`, как описано в разделе [Получение информации о пейволе](#fetch-paywall-designed-with-paywall-builder) выше. :::warning Почему мы рекомендуем использовать `getPaywall` Метод `getPaywallForDefaultAudience` имеет ряд существенных недостатков: - **Возможные проблемы с обратной совместимостью**: если нужно показывать разные пейволы для разных версий приложения (текущей и будущих), могут возникнуть сложности. Придётся либо проектировать пейволы с поддержкой текущей (устаревшей) версии, либо смириться с тем, что у пользователей этой версии пейволы могут не отображаться. - **Потеря таргетинга**: все пользователи будут видеть один и тот же пейвол, настроенный для аудитории **All Users**, — это означает отказ от персонализированного таргетинга (в том числе по странам, маркетинговой атрибуции или собственным пользовательским атрибутам). Если вас устраивают эти ограничения ради более быстрой загрузки пейвола, используйте метод `getPaywallForDefaultAudience` следующим образом. В противном случае используйте `getPaywall`, описанный [выше](#fetch-paywall-designed-with-paywall-builder). ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note Метод `getPaywallForDefaultAudience` доступен начиная с версии React Native SDK 2.11.2. ::: | Параметр | Наличие | Описание | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | обязательный | Идентификатор [плейсмента](placements). Это значение вы указали при создании плейсмента в дашборде Adapty. | | **locale** |опциональный
по умолчанию: `en`
|Идентификатор [локализации пейвола](add-remote-config-locale). Ожидается в виде языкового кода, состоящего из одного или нескольких подтегов, разделённых символом минус (**-**). Первый подтег — язык, второй — регион.
Пример: `en` означает английский, `pt-br` — бразильский португальский.
Подробнее о кодах локалей и рекомендациях по их использованию — в разделе [Локализации и коды локалей](react-native-localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае ошибки. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.
Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите вариант `.returnCacheDataElseLoad` — он возвращает кешированные данные, если они есть. В таком случае пользователи могут получить не самые свежие данные, зато загрузка будет быстрее вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при его переустановке или вручную.
| ## Настройка ресурсов \{#customize-assets\} Чтобы настроить изображения и видео на пейволе, используйте пользовательские ресурсы. У hero-изображений и видео есть предопределённые идентификаторы: `hero_image` и `hero_video`. В бандле пользовательских ресурсов вы обращаетесь к этим элементам по их идентификаторам и настраиваете их поведение. Для остальных изображений и видео необходимо [задать пользовательский идентификатор](custom-media) в дашборде Adapty. Например, вы можете: - Показывать разные изображения или видео разным пользователям. - Показывать локальное превью-изображение, пока загружается основное удалённое изображение. - Показывать превью-изображение перед запуском видео. :::important Для использования этой функции обновите Adapty React Native SDK до версии 3.8.0 или выше. ::: Вот пример того, как можно передать кастомные ресурсы через простой словарь: ```javascript const customAssets: Record
## Счётчик просмотров пейвола слишком большой \{#the-paywall-view-number-is-too-big\}
**Проблема**: Количество просмотров пейвола отображается в два раза больше ожидаемого.
**Причина**: Возможно, в коде вызывается `logShowFlow` (React Native SDK v4+) / `logShowPaywall`, что дублирует счётчик просмотров, если вы используете Paywall Builder или Flow Builder. Для флоу и пейволов, созданных с помощью этих инструментов, аналитика отслеживается автоматически, поэтому использовать этот метод не нужно.
**Решение**: Убедитесь, что в коде не вызывается `logShowFlow` (React Native SDK v4+) / `logShowPaywall`, если вы используете Paywall Builder или Flow Builder.
## Другие проблемы \{#other-issues\}
**Проблема**: Вы столкнулись с другими проблемами, связанными с Paywall Builder, которые не описаны выше.
**Решение**: При необходимости обновите SDK до последней версии, воспользовавшись [гайдами по миграции](react-native-sdk-migration-guides). Многие проблемы уже исправлены в новых версиях SDK.
---
# File: react-native-quickstart-manual
---
---
title: "Включить покупки в пользовательском пейволе в React Native SDK"
description: "Интегрируйте Adapty SDK в свои пользовательские пейволы на React Native для поддержки встроенных покупок."
---
В этом гайде описано, как интегрировать Adapty в пользовательские пейволы. Сохраняйте полный контроль над реализацией пейвола, пока Adapty SDK получает продукты, обрабатывает новые покупки и восстанавливает предыдущие.
:::important
**Это руководство предназначено для разработчиков, реализующих кастомные пейволы.** Если вы хотите самый простой способ подключить покупки, используйте [Adapty Flow Builder](react-native-quickstart-paywalls). С Flow Builder вы создаёте флоу в визуальном редакторе без кода, Adapty автоматически обрабатывает всю логику покупок, а тестировать разные дизайны можно без перепубликации приложения.
:::
## Прежде чем начать \{#before-you-start\}
### Настройка продуктов \{#set-up-products\}
Чтобы подключить встроенные покупки, нужно разобраться с тремя ключевыми понятиями:
- [**Products**](product) – всё, что пользователи могут купить (подписки, расходуемые покупки, пожизненный доступ)
- [**Paywalls**](paywalls) – конфигурации, определяющие, какие продукты предлагать. В Adapty пейволы — единственный способ получить продукты, но такой подход позволяет менять продукты, цены и офферы без изменений в коде приложения.
- [**Placements**](placements) – где и когда показывать пейволы в приложении (например, `main`, `onboarding`, `settings`). Вы настраиваете пейволы для плейсментов в дашборде, а затем запрашиваете их по ID плейсмента в коде. Это упрощает запуск A/B-тестов и показ разных пейволов разным пользователям.
Убедитесь, что вы понимаете эти концепции, даже если используете собственный пейвол. По сути, это просто способ управлять продуктами, которые вы продаёте в приложении.
Чтобы реализовать собственный пейвол, нужно создать **пейвол** и добавить его в **плейсмент**. Это позволит получать продукты. Чтобы разобраться, что нужно сделать в дашборде, следуйте quickstart-гайду [здесь](quickstart).
### Управление пользователями \{#manage-users\}
Вы можете работать как с backend-аутентификацией, так и без неё.
Тем не менее Adapty SDK по-разному обрабатывает анонимных и идентифицированных пользователей. Прочитайте [гайд по быстрой идентификации](react-native-quickstart-identify), чтобы разобраться в деталях и убедиться, что вы правильно работаете с пользователями.
## Шаг 1. Получите продукты \{#step-1-get-products\}
Чтобы получить продукты для вашего кастомного пейвола, нужно:
1. Получить объект `flow`, передав ID [плейсмента](placements) в метод `getFlow`.
2. Получить массив продуктов для этого флоу с помощью метода `getPaywallProducts`.
```typescript showLineNumbers
async function loadPaywall() {
try {
const flow: AdaptyFlow = await adapty.getFlow('YOUR_PLACEMENT_ID');
const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts(flow);
// Use products to build your custom paywall UI
} catch (error) {
// Handle the error
}
}
```
## Шаг 2. Обработка покупок \{#step-2-accept-purchases\}
Когда пользователь нажимает на продукт в вашем кастомном пейволе, вызовите метод `makePurchase` с выбранным продуктом. Он обработает флоу покупки и вернёт обновлённый профиль.
```typescript showLineNumbers
async function purchaseProduct(product: AdaptyPaywallProduct) {
try {
const purchaseResult: AdaptyPurchaseResult = await adapty.makePurchase(product);
switch (purchaseResult.type) {
case 'success':
// Purchase successful, profile updated
break;
case 'user_cancelled':
// User canceled the purchase
break;
case 'pending':
// Purchase is pending (e.g., user will pay offline with cash)
break;
}
} catch (error) {
// Handle the error
}
}
```
## Шаг 3. Восстановление покупок \{#step-3-restore-purchases\}
Сторы требуют, чтобы во всех приложениях с подписками была возможность восстановить покупки.
Вызывайте метод `restorePurchases`, когда пользователь нажимает кнопку восстановления. Это синхронизирует историю покупок с Adapty и вернёт обновлённый профиль.
```typescript showLineNumbers
async function restorePurchases() {
try {
const profile: AdaptyProfile = await adapty.restorePurchases();
// Restore successful, profile updated
} catch (error) {
// Handle the error
}
}
```
## Следующие шаги \{#next-steps\}
:::tip
Есть вопросы или возникли проблемы? Загляните на наш [форум поддержки](https://adapty.featurebase.app/), где можно найти ответы на распространённые вопросы или задать свой. Наша команда и сообщество всегда готовы помочь!
:::
Ваш пейвол готов к отображению в приложении. Протестируйте покупки в [песочнице App Store](test-purchases-in-sandbox) или в [Google Play Store](testing-on-android), чтобы убедиться, что тестовая покупка через пейвол проходит успешно. Чтобы увидеть, как это работает в готовой к продакшену реализации, изучите [CustomPurchaseScreen.tsx](https://github.com/adaptyteam/AdaptySDK-React-Native/blob/master/examples/ExpoGoWebMock/src/CustomPurchaseScreen.tsx) в нашем примере приложения — там показана обработка покупок с правильной обработкой ошибок, состояниями загрузки и управлением состоянием UI.
Затем [проверьте, совершил ли пользователь покупку](react-native-check-subscription-status), чтобы решить, показывать ли пейвол или открыть доступ к платным функциям.
---
# File: fetch-paywalls-and-products-react-native
---
---
title: "Получение пейволов и продуктов для пейволов с Remote Config в React Native SDK"
description: "Получайте пейволы и продукты в Adapty React Native SDK для улучшения монетизации пользователей."
---
По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае сбоя. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают актуальные данные.
Однако если вы считаете, что у ваших пользователей нестабильный интернет, рассмотрите использование `.returnCacheDataElseLoad`: оно возвращает кешированные данные, если они есть. В этом случае пользователи могут не получать самые свежие данные, зато загрузка будет быстрее независимо от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при его переустановке или принудительной очистке.
Adapty SDK хранит флоу и пейволы в двух слоях: регулярно обновляемый кеш, описанный выше, и [резервные пейволы](react-native-use-fallback-paywalls). Также используется CDN для более быстрой загрузки флоу и пейволов, а также отдельный резервный сервер на случай недоступности CDN. Эта система обеспечивает получение последней версии флоу и надёжность работы даже при плохом интернет-соединении.
| | **loadTimeoutMs** | по умолчанию: 5 сек |Это значение ограничивает таймаут для данного метода. По истечении таймаута будут возвращены кешированные данные или локальный резервный вариант.
Обратите внимание: в редких случаях метод может завершиться с небольшой задержкой относительно значения, указанного в `loadTimeout`, так как операция может включать несколько запросов под капотом.
| :::note В v4 метод `getFlow` больше не принимает параметр `locale`. Для кастомных пейволов все доступные локали возвращаются в Remote Config флоу (`flow.remoteConfigs`) — выберите ту, которая соответствует настройкам устройства или приложения пользователя. ::: Не указывайте ID продуктов жёстко в коде! Поскольку флоу настраиваются удалённо, доступные продукты, их количество и специальные предложения (например, бесплатные пробные периоды) могут меняться со временем. Убедитесь, что ваш код обрабатывает подобные сценарии. Например, если изначально вы получаете 2 продукта, приложение должно отображать именно 2 продукта. Но если позднее вы получите 3 продукта, приложение должно отобразить все 3 без каких-либо изменений в коде. Единственное, что нужно указать жёстко, — это ID плейсмента. Параметры ответа: | Параметр | Описание | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Объект `AdaptyFlow`, содержащий плейсмент, идентификаторы (`id`, `variationId`), название, варианты пейвола (`paywalls`) и массив `remoteConfigs` (по одной записи на каждую настроенную локаль). Чтобы получить продукты для флоу, вызовите `getPaywallProducts(flow)`. | ## Получение продуктов \{#fetch-products\} Получив флоу, вы можете запросить массив продуктов, соответствующих ему: ```typescript showLineNumbers try { // ...flow const products = await adapty.getPaywallProducts(flow); // the requested products list } catch (error) { // handle the error } ``` Параметры ответа: | Parameter | Description | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Список объектов [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) с: идентификатором продукта, названием продукта, ценой, валютой, длительностью подписки и рядом других свойств. | При реализации собственного дизайна пейвола вам, скорее всего, потребуется доступ к свойствам объекта [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct). Ниже показаны наиболее часто используемые свойства, но полный список всех доступных свойств см. в документации по ссылке. | Свойство | Описание | |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Чтобы отобразить название продукта, используйте `product.localizedTitle`. Обратите внимание, что локализация основана на стране стора, выбранной пользователем, а не на языке устройства. | | **Price** | Чтобы отобразить локализованную цену, используйте `product.price?.localizedString`. Локализация основана на настройках языка устройства. Цену в виде числа можно получить через `product.price?.amount` — значение будет указано в местной валюте. Символ валюты доступен через `product.price?.currencySymbol`. | | **Subscription Period** | Чтобы отобразить период подписки (например, неделя, месяц, год и т. д.), используйте `product.subscription?.localizedSubscriptionPeriod`. Локализация основана на настройках языка устройства. Для программного получения периода подписки используйте `product.subscription?.subscriptionPeriod`. Через свойство `unit` можно узнать единицу периода: `'day'`, `'week'`, `'month'`, `'year'` или `'unknown'`. Свойство `numberOfUnits` возвращает количество единиц периода. Например, для квартальной подписки в `unit` будет `'month'`, а в `numberOfUnits` — `3`. | | **Introductory Offer** | Чтобы показать бейдж или другой индикатор наличия introductory offer, проверьте свойство `product.subscription?.offer?.phases`. Это список, который может содержать до двух фаз скидки: фазу бесплатного пробного периода и фазу вводной цены. В каждом объекте фазы доступны следующие полезные свойства:По умолчанию SDK пытается загрузить данные с сервера и возвращает кэшированные данные в случае сбоя. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают самые актуальные данные.
Однако если вы считаете, что у ваших пользователей нестабильный интернет, рассмотрите использование `.returnCacheDataElseLoad` для возврата кэшированных данных, если они существуют. В этом случае пользователи могут не получить самые последние данные, но загрузка будет быстрее, независимо от качества соединения. Кэш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание, что кэш сохраняется при перезапуске приложения и очищается только при переустановке приложения или вручную.
|необязательный
по умолчанию: `en`
|Идентификатор [локализации пейвола](add-remote-config-locale). Ожидается языковой код, состоящий из одного или нескольких подтегов, разделённых символом минус (**-**). Первый подтег обозначает язык, второй — регион.
Например: `en` — английский, `pt-br` — бразильский португальский.
Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе [Локализации и коды локалей](react-native-localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае ошибки. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.
Если вы считаете, что у ваших пользователей нестабильное интернет-соединение, рассмотрите использование `.returnCacheDataElseLoad` — оно возвращает кешированные данные, если они есть. В этом случае пользователи могут не получить самые свежие данные, зато загрузка будет быстрее вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется после перезапуска приложения и очищается только при его переустановке или вручную.
Adapty SDK хранит пейволы на двух уровнях: регулярно обновляемый кеш, описанный выше, и [резервные пейволы](react-native-use-fallback-paywalls). Для более быстрой загрузки пейволов используется CDN, а на случай его недоступности — отдельный резервный сервер. Эта система обеспечивает получение актуальных версий пейволов и надёжную работу даже при нестабильном интернет-соединении.
| | **loadTimeoutMs** | по умолчанию: 5 сек |Это значение ограничивает тайм-аут метода. По истечении тайм-аута возвращаются кешированные данные или локальный резервный вариант.
Обратите внимание: в редких случаях тайм-аут метода может наступить чуть позже указанного в `loadTimeout`, поскольку операция может включать несколько запросов под капотом.
| Не задавайте идентификаторы продуктов жёстко в коде! Поскольку пейволы настраиваются удалённо, доступные продукты, их количество и специальные предложения (например, бесплатные пробные периоды) могут меняться со временем. Убедитесь, что ваш код учитывает эти сценарии. Например, если изначально вы получаете 2 продукта, приложение должно отображать эти 2 продукта. Но если позже вы получите 3 продукта, приложение должно показать все 3 без каких-либо изменений в коде. Единственное, что нужно задать жёстко, — это идентификатор плейсмента. Параметры ответа: | Параметр | Описание | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Объект [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) с: списком идентификаторов продуктов, идентификатором пейвола, Remote Config и рядом других свойств. | ## Получение продуктов \{#fetch-products\} Получив пейвол, вы можете запросить массив продуктов, соответствующих ему: ```typescript showLineNumbers try { // ...paywall const products = await adapty.getPaywallProducts(paywall); // the requested products list } catch (error) { // handle the error } ``` Параметры ответа: | Параметр | Описание | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Список объектов [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) с идентификатором продукта, названием продукта, ценой, валютой, длительностью подписки и рядом других свойств. | При реализации собственного дизайна пейвола вам, скорее всего, понадобятся свойства объекта [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct). Ниже приведены наиболее часто используемые свойства; полный список доступных свойств смотрите в документации по ссылке. | Свойство | Описание | |-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Чтобы отобразить название продукта, используйте `product.localizedTitle`. Локализация основана на стране стора, выбранной пользователем, а не на локали устройства. | | **Price** | Чтобы отобразить цену в локализованном формате, используйте `product.price?.localizedString`. Локализация основана на локали устройства. Также можно получить цену как число через `product.price?.amount` — значение будет в местной валюте. Чтобы получить символ валюты, используйте `product.price?.currencySymbol`. | | **Subscription Period** | Чтобы отобразить период (например, неделя, месяц, год и т. д.), используйте `product.subscription?.localizedSubscriptionPeriod`. Локализация основана на локали устройства. Для программного получения периода подписки используйте `product.subscription?.subscriptionPeriod`. Через свойство `unit` можно узнать единицу периода: `'day'`, `'week'`, `'month'`, `'year'` или `'unknown'`. Свойство `numberOfUnits` возвращает количество единиц периода. Например, для квартальной подписки в `unit` будет `'month'`, а в `numberOfUnits` — `3`. | | **Introductory Offer** | Чтобы показать бейдж или другой индикатор наличия introductory offer, проверьте свойство `product.subscription?.offer?.phases`. Это список, который может содержать до двух фаз скидки: фаза бесплатного пробного периода и фаза вводной цены. Каждый объект фазы содержит следующие полезные свойства:опциональный
по умолчанию: `en`
|Идентификатор [локализации пейвола](add-remote-config-locale). Ожидается, что этот параметр будет языковым кодом, состоящим из одного или нескольких подтегов, разделённых символом «минус» (**-**). Первый подтег обозначает язык, второй — регион.
Пример: `en` означает английский, `pt-br` — бразильский португальский.
Подробнее о кодах локалей и рекомендуемом подходе к их использованию см. в разделе [Локализации и коды локалей](react-native-localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае ошибки. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают актуальные данные.
Однако если вы считаете, что ваши пользователи работают в условиях нестабильного интернета, рассмотрите использование `.returnCacheDataElseLoad` — оно возвращает кешированные данные, если они есть. В этом случае пользователи могут получать не самые последние данные, зато загрузка будет быстрее вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы сократить количество сетевых запросов.
Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при его переустановке или вручную.
|Если запрос выполнен успешно, ответ содержит этот объект. Объект [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) предоставляет исчерпывающую информацию об уровнях доступа пользователя, подписках и разовых покупках в приложении.
Проверьте статус уровня доступа, чтобы убедиться, что у пользователя есть необходимый доступ к приложению.
| :::warning **Примечание:** если вы используете Apple StoreKit версии ниже 2.0 и Adapty SDK версии ниже 2.9.0, вам нужно указать [общий секрет Apple App Store](app-store-connection-configuration#step-5-enter-app-store-shared-secret) вместо этого. Данный метод в настоящее время устарел согласно Apple. ::: ## Смена подписки при совершении покупки \{#change-subscription-when-making-a-purchase\} Когда пользователь выбирает новую подписку вместо продления текущей, поведение зависит от стора: - В App Store подписка обновляется автоматически в рамках группы подписок. Если пользователь покупает подписку из одной группы, уже имея активную подписку из другой, обе подписки будут активны одновременно. - В Google Play подписка не обновляется автоматически. Переключение нужно реализовать в коде приложения, как описано ниже. Чтобы заменить подписку другой в Android, вызовите метод `.makePurchase()` с дополнительным параметром: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product, params); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` Дополнительный параметр запроса: | Параметр | Наличие | Описание | | :--------- | :------- | :----------------------------------------------------------- | | **params** | обязательный | объект типа [`MakePurchaseParamsInput`](https://react-native.adapty.io/types/makepurchaseparamsinput). | :::info **Версия 3.8.2+**: Структура `MakePurchaseParamsInput` была обновлена. `oldSubVendorProductId` и `prorationMode` теперь вложены в `subscriptionUpdateParams`, а `isOfferPersonalized` перемещён на верхний уровень. ```javascript makePurchase(product, { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } }); ``` ::: Подробнее о подписках и режимах замены можно прочитать в документации для разработчиков Google: - [О режимах замены](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Рекомендации Google по режимам замены](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Режим замены [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Примечание: этот метод доступен только для апгрейда подписки. Даунгрейд не поддерживается. - Режим замены [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Примечание: фактическая смена подписки произойдёт только по окончании текущего расчётного периода. ## Активация промокодов в iOS \{#redeem-offer-codes-in-ios\}Объект [`AdaptyProfile`](https://react-native.adapty.io/interfaces/adaptyprofile). Эта модель содержит информацию об уровнях доступа, подписках и разовых покупках.
Проверьте **статус уровня доступа**, чтобы определить, есть ли у пользователя доступ к приложению.
| :::tip Хотите увидеть реальный пример интеграции Adapty SDK в мобильное приложение? Посмотрите наши [примеры приложений](sample-apps) — они демонстрируют полную настройку: отображение пейволов, совершение покупок и другие базовые функции. ::: --- # File: implement-observer-mode-react-native --- --- title: "Implement Observer mode in React Native SDK" description: "Реализация режима наблюдателя в Adapty для отслеживания событий подписки пользователей в React Native SDK." --- Если у вас уже есть собственная инфраструктура для покупок и вы не готовы полностью переходить на Adapty, вы можете попробовать [Observer mode](observer-vs-full-mode). В базовом виде Observer Mode предлагает расширенную аналитику и бесшовную интеграцию с системами атрибуции и аналитики. Если это вам подходит, нужно сделать только следующее: 1. Включить его при настройке Adapty SDK, установив параметр `observerMode` в `true`. Следуйте инструкциям по настройке для [React Native](sdk-installation-reactnative). 2. [Передавать транзакции](report-transactions-observer-mode-react-native) из вашей существующей инфраструктуры покупок в Adapty. ### Настройка Observer mode \{#observer-mode-setup\} Включите Observer mode, если вы самостоятельно обрабатываете покупки и статус подписки, а Adapty используете только для отправки событий подписки и аналитики. :::important В режиме Observer mode Adapty SDK не закрывает транзакции — убедитесь, что вы обрабатываете их самостоятельно. ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { observerMode: true, // Enable observer mode }); ``` Параметры: | Параметр | Описание | | --------------------------- | ------------------------------------------------------------ | | observerMode | Булево значение, которое управляет [Observer mode](observer-vs-full-mode). Значение по умолчанию: `false`. | ## Использование пейволов Adapty в Observer Mode \{#using-adapty-paywalls-in-observer-mode\} Если вы также хотите использовать пейволы Adapty и возможности A/B-тестирования — это возможно, но в Observer mode потребует дополнительной настройки. Вот что нужно сделать помимо шагов выше: 1. Отображайте пейволы как обычно для [пейволов на базе Remote Config](present-remote-config-paywalls-react-native). 3. [Привяжите пейволы](report-transactions-observer-mode-react-native) к транзакциям покупок. --- # File: report-transactions-observer-mode-react-native --- --- title: "Отчёт о транзакциях в Observer Mode в React Native SDK" description: "Отчитывайтесь о транзакциях покупок в Adapty Observer Mode для отслеживания данных о пользователях и доходах в React Native SDK." ---Для iOS, StoreKit 1: объект [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Для iOS, StoreKit 2: объект [Transaction](https://developer.apple.com/documentation/storekit/transaction).
Для Android: строковый идентификатор (purchase.getOrderId) покупки, где покупка является экземпляром класса [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) из библиотеки биллинга.
| | variationId | обязательный | Строковый идентификатор варианта. Его можно получить через свойство `variationId` объекта [AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall). |phoneNumber
firstName
lastName
| String | | gender | Enum, допустимые значения: `female`, `male`, `other` | | birthday | Date | ### Пользовательские атрибуты \{#custom-user-attributes\} Вы можете задавать собственные атрибуты — как правило, они связаны с тем, как пользователь работает с приложением. Например, в фитнес-приложении это может быть количество тренировок в неделю, в приложении для изучения языков — уровень знаний. Атрибуты можно использовать в сегментах для создания целевых пейволов и предложений, а также в аналитике, чтобы выяснить, какие продуктовые метрики сильнее всего влияют на выручку. ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); } catch (error) { // handle `AdaptyError` } ``` Чтобы удалить существующий ключ, используйте метод `.withRemoved(customAttributeForKey:)`: ```typescript showLineNumbers try { // to remove a key, pass null as its value await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); } catch (error) { // handle `AdaptyError` } ``` Иногда нужно узнать, какие пользовательские атрибуты уже были установлены. Для этого используйте поле `customAttributes` объекта `AdaptyProfile`. :::warning Имейте в виду, что значение `customAttributes` может быть устаревшим: атрибуты могут отправляться с разных устройств в любое время, поэтому данные на сервере могут измениться после последней синхронизации. ::: ### Ограничения \{#limits\} - Не более 30 пользовательских атрибутов на пользователя - Длина имени ключа — не более 30 символов. Допустимы буквенно-цифровые символы и следующие знаки: `_` `-` `.` - Значение может быть строкой или числом с плавающей точкой длиной не более 50 символов. --- # File: react-native-listen-subscription-changes --- --- title: "Проверка статуса подписки в React Native SDK" description: "Отслеживайте и управляйте статусом подписки пользователей в Adapty для повышения удержания клиентов в вашем React Native приложении." --- С Adapty отслеживать статус подписки очень просто. Вам не нужно вручную прописывать идентификаторы продуктов в коде — достаточно проверить наличие активного [уровня доступа](access-level).Объект [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile). Как правило, для определения наличия у пользователя премиум-доступа к приложению достаточно проверить статус уровня доступа в профиле.
Метод `.getProfile` возвращает наиболее актуальный результат, поскольку всегда пытается обратиться к API. Если по какой-то причине (например, при отсутствии интернет-соединения) Adapty SDK не может получить данные с сервера, возвращаются данные из кэша. Важно учитывать, что Adapty SDK регулярно обновляет кэш `AdaptyProfile`, чтобы поддерживать информацию в актуальном состоянии.
| Метод `.getProfile()` возвращает профиль пользователя, из которого можно получить статус уровня доступа. В приложении может быть несколько уровней доступа. Например, в новостном приложении с независимыми подписками на разные разделы можно создать уровни доступа «sports» и «science». Однако в большинстве случаев достаточно одного уровня доступа — стандартного «premium». Пример проверки стандартного уровня доступа «premium»: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels?.["premium"]?.isActive; if (isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` ### Прослушивание обновлений статуса подписки \{#listening-for-subscription-status-updates\} При каждом изменении подписки пользователя Adapty генерирует событие. Чтобы получать сообщения от Adapty, выполните дополнительную настройку: ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addEventListener('onLatestProfileLoad', profile => { // handle any changes to subscription state }); ``` Adapty также генерирует событие при запуске приложения — в этом случае передаётся кэшированный статус подписки. ### Кэш статуса подписки \{#subscription-status-cache\} Кэш, реализованный в Adapty SDK, хранит статус подписки профиля. Это означает, что даже при недоступности сервера кэшированные данные позволяют получить информацию о статусе подписки профиля. Вместе с тем прямые запросы данных из кэша невозможны. SDK периодически опрашивает сервер каждую минуту для проверки обновлений профиля. При наличии изменений — новых транзакций или других обновлений — они передаются в кэшированные данные для синхронизации с сервером. --- # File: react-native-deal-with-att --- --- title: "Работа с ATT в React Native SDK" description: "Начните работу с Adapty на React Native для упрощения настройки подписок и управления ими." --- Если ваше приложение использует фреймворк AppTrackingTransparency и отображает пользователю запрос на авторизацию отслеживания, необходимо передать [статус авторизации](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) в Adapty. ```typescript showLineNumbers try { await adapty.updateProfile({ // you can also pass a string value (validated via tsc) if you prefer appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); } catch (error) { // handle `AdaptyError` } ``` :::warning Настоятельно рекомендуем передавать это значение как можно раньше при его изменении — только в этом случае данные будут своевременно отправлены в настроенные вами интеграции. ::: --- # File: kids-mode-react-native --- --- title: "Режим для детей в React Native SDK" description: "Легко включите режим для детей, чтобы соответствовать политикам Apple и Google. IDFA, GAID и рекламные данные не собираются в React Native SDK." --- Если ваше приложение на React Native предназначено для детей, вы должны соблюдать политики [Apple](https://developer.apple.com/kids/) и [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Если вы используете Adapty SDK, несколько простых шагов помогут настроить его в соответствии с этими политиками и пройти проверку в сторах. :::important На iOS Kids Mode включается через трейт Swift Package `KidsMode`, который исключает из сборки весь код, связанный с IDFA, AdSupport и AppTrackingTransparency. Для этого требуется SDK v4 (который устанавливает нативный iOS SDK через Swift Package Manager) и **Xcode 26** или новее. См. раздел [Изменения в iOS Podfile](#updates-in-your-ios-podfile) ниже. ::: ## Что нужно настроить? \{#whats-required\} Вам нужно настроить SDK, чтобы отключить сбор следующих данных: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [IP-адрес](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Кроме того, рекомендуем осторожно обращаться с customer user ID. Идентификатор в формате `опциональный
по умолчанию: `en`
|Идентификатор локализации онбординга. Ожидается языковой код, состоящий из одного или двух подтегов, разделённых символом минус (**-**). Первый подтег обозначает язык, второй — регион.
Пример: `en` — английский, `pt-br` — бразильский португальский.
Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе [Локализации и коды локалей](localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае сбоя. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают актуальные данные.
Однако если у ваших пользователей нестабильный интернет, рассмотрите вариант `.returnCacheDataElseLoad` — он возвращает кешированные данные, если они есть. В этом случае пользователи могут получить не самые свежие данные, зато загрузка будет быстрее вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.
Обратите внимание: кеш сохраняется после перезапуска приложения и очищается только при его переустановке или принудительной очистке вручную.
Adapty SDK хранит онбординги локально в двух слоях: регулярно обновляемый кеш, описанный выше, и резервные онбординги. Для более быстрой загрузки онбордингов используется CDN, а на случай его недоступности — отдельный резервный сервер. Такая система гарантирует, что вы всегда получаете актуальную версию онбордингов, сохраняя надёжность даже при слабом интернет-соединении.
| | **loadTimeoutMs** | по умолчанию: 5 сек |Это значение ограничивает таймаут метода. Если таймаут истекает, возвращаются кешированные данные или локальный резервный вариант.
Обратите внимание: в редких случаях метод может завершиться чуть позже указанного в `loadTimeout` значения, поскольку операция может включать несколько внутренних запросов.
| Параметры ответа: | Параметр | Описание | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Объект [`AdaptyOnboarding`](https://react-native.adapty.io/interfaces/adaptyonboarding) с: идентификатором и конфигурацией онбординга, Remote Config и рядом других свойств. | ## Ускорьте получение онбординга с помощью онбординга для аудитории по умолчанию \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Как правило, онбординги загружаются почти мгновенно, поэтому беспокоиться об ускорении этого процесса не нужно. Однако если у вас много аудиторий и онбордингов, а у пользователей слабое интернет-соединение, загрузка онбординга может занять больше времени, чем хотелось бы. В таких случаях имеет смысл показывать онбординг по умолчанию — чтобы пользователь видел хоть что-то, а не пустой экран. Чтобы решить эту проблему, воспользуйтесь методом `getOnboardingForDefaultAudience`, который получает онбординг указанного плейсмента для аудитории **All Users**. Однако важно понимать, что рекомендуемый подход — получать онбординг с помощью метода `getOnboarding`, как описано в разделе [Получение онбординга](#fetch-onboarding) выше. :::warning Используйте `getOnboarding` вместо `getOnboardingForDefaultAudience`, поскольку последний имеет существенные ограничения: - **Проблемы совместимости**: Может вызывать сложности при поддержке нескольких версий приложения — придётся либо проектировать с учётом обратной совместимости, либо мириться с тем, что старые версии могут отображать контент некорректно. - **Без персонализации**: Показывает контент только для аудитории «All Users», без таргетинга по стране, атрибуции или пользовательским атрибутам. Если для вашего сценария скорость загрузки важнее этих недостатков, используйте `getOnboardingForDefaultAudience`, как показано ниже. В противном случае используйте `getOnboarding`, как описано [выше](#fetch-onboarding). ::: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboardingForDefaultAudience(placementId, locale); // запрошенный онбординг } catch (error) { // обработка ошибки } ``` Параметры: | Параметр | Наличие | Описание | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | обязательный | Идентификатор нужного [плейсмента](placements). Это значение вы указали при создании плейсмента в дашборде Adapty. | | **locale** |опциональный
по умолчанию: `en`
|Идентификатор локализации онбординга. Ожидается языковой код, состоящий из одного или двух подтегов, разделённых символом минус (**-**). Первый подтег обозначает язык, второй — регион.
Например: `en` — английский язык, `pt-br` — бразильский португальский.
Подробнее о кодах локалей и рекомендациях по их использованию — в разделе [Локализации и коды локалей](localizations-and-locale-codes).
| | **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` |По умолчанию SDK пытается загрузить данные с сервера и в случае сбоя возвращает кэшированные данные. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.
Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование `.returnCacheDataElseLoad` — этот режим возвращает кэшированные данные, если они есть. В таком сценарии пользователи могут получить не самые последние данные, но загрузка будет быстрее независимо от качества соединения. Кэш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы сократить количество сетевых запросов.
Обратите внимание: кэш сохраняется при перезапуске приложения и очищается только при его переустановке или вручную.
Adapty SDK хранит онбординги локально в двух слоях: регулярно обновляемый кэш, описанный выше, и резервные онбординги. Для более быстрой загрузки мы также используем CDN и отдельный резервный сервер на случай недоступности CDN. Эта система гарантирует, что вы всегда получаете актуальную версию онбордингов, сохраняя надёжность даже при нестабильном интернете.
| --- # File: react-native-present-onboardings --- --- title: "Отображение онбордингов в React Native SDK" description: "Узнайте, как отображать онбординги на React Native для повышения конверсии и дохода." --- :::warning **Онбординги устарели в SDK v4 и будут удалены в одном из следующих релизов.** Они больше не получают исправлений и улучшений. Используйте [флоу](react-native-get-pb-paywalls) вместо них: в отличие от онбордингов, которые работают внутри WebView, флоу рендерятся нативно на устройстве — это даёт более плавные анимации, единый нативный стиль, быструю загрузку и отсутствие зависимости от WebView. Смотрите [Получение флоу и пейволов](react-native-get-pb-paywalls) и [Отображение флоу и пейволов](react-native-present-paywalls), чтобы начать работу. ::: Если вы настроили онбординг с помощью билдера, вам не нужно беспокоиться о его отрисовке в коде мобильного приложения для показа пользователю. Такой онбординг содержит и то, что должно отображаться, и то, как это должно выглядеть. Перед началом убедитесь, что: 1. Вы установили [Adapty React Native SDK](sdk-installation-reactnative) версии 3.8.0 или новее. 2. Вы [создали онбординг](create-onboarding). 3. Вы добавили онбординг в [плейсмент](placements). Adapty React Native SDK предоставляет два способа показа онбордингов: - **React-компонент**: встроенный компонент позволяет интегрировать его в архитектуру приложения и систему навигации. - **Модальное представление** ## React-компонент \{#react-component\} Чтобы встроить онбординг в существующее дерево компонентов, используйте компонент `AdaptyOnboardingView` напрямую в иерархии React Native-компонентов. Встроенный компонент позволяет интегрировать его в архитектуру и навигационную систему приложения. :::note На Android рекомендуем выполнить дополнительную настройку `AdaptyOnboardingView`, чтобы избежать визуального артефакта при рендеринге. См. [Системный UI перекрывает контент онбординга на Android](#system-ui-overlaps-onboarding-content-on-android). :::
Затем этот ID можно использовать в коде и обрабатывать его как пользовательское действие. Например, если пользователь нажимает кастомную кнопку — **Login** или **Allow notifications** — обработчик события сработает с параметром `actionId`, соответствующим **Action ID** из билдера. Вы можете задавать собственные ID, например `"allowNotifications"`.
:::important
Обратите внимание, что вам нужно самостоятельно обработать ситуацию, когда пользователь закрывает онбординг. Например, необходимо прекратить его отображение.
:::
2. Нажмите на название группы подписок. Вы увидите свои продукты в разделе **Subscriptions**.
3. Убедитесь, что тестируемый продукт отмечен как **Ready to Submit**.
4. Сравните ID продукта из таблицы с тем, что указан во вкладке [**Products**](https://app.adapty.io/products) дашборда Adapty. Если ID не совпадают, скопируйте ID продукта из таблицы и [создайте продукт](create-product) с этим ID в дашборде Adapty.
## Шаг 3. Проверьте доступность продукта \{#step-4-check-product-availability\}
1. Вернитесь в **App Store Connect** и откройте раздел **Subscriptions**.
2. Нажмите на название группы подписок, чтобы просмотреть ваши продукты.
3. Выберите продукт, который хотите протестировать.
4. Прокрутите до раздела **Availability** и убедитесь, что в нём перечислены все необходимые страны и регионы.
## Шаг 4. Проверьте цены продуктов \{#step-5-check-product-prices\}
1. Снова откройте раздел **Monetization** → **Subscriptions** в **App Store Connect**.
2. Нажмите на название группы подписок.
3. Выберите продукт, который хотите протестировать.
4. Прокрутите вниз до раздела **Subscription Pricing** и раскройте секцию **Current Pricing for New Subscribers**.
5. Убедитесь, что все необходимые цены указаны.
## Шаг 5. Убедитесь, что статус приложения, банковский счёт и налоговые формы активны \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. На главной странице [**App Store Connect**](https://appstoreconnect.apple.com/) нажмите **Business**.
2. Выберите название своей компании.
3. Прокрутите вниз и убедитесь, что ваши **Paid Apps Agreement**, **Bank Account** и **Tax forms** отображаются как **Active**.
Выполнив эти шаги, вы сможете устранить предупреждение `InvalidProductIdentifiers` и запустить продукты в сторе.
## Шаг 6. Пересоздайте продукт, если он завис \{#step-6-recreate-the-product-if-its-stuck\}
Шаги 1–5 могут пройти успешно — статус `Approved`, совпадающий Bundle ID, рабочий API-ключ — но SDK всё равно возвращает `1000 noProductIDsFound`. В таком случае продукт, возможно, завис в реестре Apple. Реестр продуктов Apple иногда переходит в состояние, при котором продукт существует в интерфейсе App Store Connect, но недоступен через путь поиска StoreKit.
Удалите продукт в App Store Connect и пересоздайте его с тем же идентификатором. После пересоздания подождите до 24 часов, пока изменения распространятся.
---
# File: cantMakePayments-react-native
---
---
title: "Исправление ошибки Code-1003 cantMakePayment в React Native SDK"
description: "Решение ошибки при совершении покупок при управлении подписками в Adapty."
---
Ошибка 1003, `cantMakePayments`, означает, что на этом устройстве нельзя совершать встроенные покупки.
Если вы столкнулись с ошибкой `cantMakePayments`, обычно это происходит по одной из следующих причин:
- Ограничения устройства: ошибка не связана с Adapty. Способы решения описаны ниже.
- Настройка Observer mode: метод `makePurchase` и Observer mode нельзя использовать одновременно. Подробнее — в соответствующем разделе ниже.
## Проблема: ограничения устройства \{#issue-device-restrictions\}
| Проблема | Решение |
|---------------------------------|-------------------------------------------------------------------------------------------------------------------|
| Ограничения Screen Time | Отключите ограничения встроенных покупок в [Screen Time](https://support.apple.com/en-us/102470) |
| Аккаунт заблокирован | Обратитесь в службу поддержки Apple для решения проблем с аккаунтом |
| Региональные ограничения | Используйте аккаунт App Store из поддерживаемого региона |
## Проблема: одновременное использование Observer mode и makePurchase \{#issue-using-both-observer-mode-and-makepurchase\}
Если вы используете `makePurchase` для обработки покупок, Observer mode не нужен. [Observer mode](observer-vs-full-mode) требуется только в том случае, если логику покупок вы реализуете самостоятельно.
Таким образом, если вы используете `makePurchase`, можно смело убрать активацию Observer mode из кода инициализации SDK.
---
# File: migration-to-react-native-sdk-v4
---
---
title: "Миграция Adapty React Native SDK на v. 4.0"
description: "Перейдите на Adapty React Native SDK v4.0 (beta): замените paywall API на flow API, совместимые как с Flow Builder, так и с Paywall Builder."
---
Adapty React Native SDK 4.0 (beta) вводит флоу и переименовывает paywall API соответствующим образом. Новые API работают как с новым Flow Builder, так и с существующим Paywall Builder — никаких изменений в настройках дашборда Adapty не требуется.
## Краткий справочник \{#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` (тип) | `AdaptyFlow` |
| `createPaywallView(paywall)` | `createFlowView(flow)` |
| `AdaptyPaywallView` (компонент) | `AdaptyFlowView` |
| `EventHandlers` (тип) | `FlowEventHandlers` |
| `onPaywallShown` | `onAppeared` |
| `onPaywallClosed` | `onDisappeared` |
| `onRenderingFailed` | `onError` |
`AdaptyPaywallProduct` сохраняет своё название — продукты по-прежнему принадлежат флоу, а `getPaywallProducts` теперь принимает `AdaptyFlow`. Методы `getFlow` и `getFlowForDefaultAudience` больше не принимают параметр `locale`. Методы представления `present`, `dismiss`, `setEventHandlers` и `showDialog`, а также обработчики событий `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` и `onAndroidSystemBack` сохраняют те же названия, что и в v3. Некоторые стандартные поведения изменились — см. [Изменения стандартного поведения](#default-behavior-changes).
## Минимальная версия iOS \{#minimum-ios-version\}
Adapty React Native SDK 4.0 повышает минимальную версию iOS с 13.0 до **iOS 15.0**. Перед обновлением установите значение deployment target не ниже 15.0.
## Установка \{#installation\}
### Обновите пакет \{#update-the-package\}
v4.0 — это предварительный релиз, поэтому укажите точную версию — npm не выбирает предварительные версии через диапазоны с `^` или `~`:
```bash showLineNumbers
npm install react-native-adapty@4.0.0
# or
yarn add react-native-adapty@4.0.0
```
### iOS: нативные SDK теперь подключаются через Swift Package Manager \{#ios-native-sdks-now-come-through-swift-package-manager\}
[Репозиторий спецификаций CocoaPods переходит в режим только для чтения в декабре 2026 года](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), поэтому начиная с v4 нативные SDK `Adapty`, `AdaptyUI` и `AdaptyPlugin` **больше не подключаются как под-зависимости CocoaPods** — podspec подтягивает их через **Swift Package Manager** (с помощью хелпера `spm_dependency`). Это требует двух вещей:
- **React Native 0.75 или новее** — нужна для вспомогательного подспека `spm_dependency`. На более старой версии `pod install` завершится с явной ошибкой; сначала обновите React Native или оставайтесь на `react-native-adapty` 3.x.
- **Динамические фреймворки** — зависимости SPM требуют динамической компоновки. Способ её включения отличается для Expo и обычного React Native.
#### Expo
Добавьте конфиг-плагин [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/) и задайте динамическую компоновку iOS-фреймворков в `app.json` (или `app.config.js`):
```json showLineNumbers title="app.json"
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"ios": {
"useFrameworks": "dynamic"
}
}
]
]
}
}
```
Затем установите плагин и пересоздайте нативный проект:
```bash showLineNumbers
npx expo install expo-build-properties
npx expo prebuild --clean
```
#### Bare React Native
Добавьте динамические фреймворки в iOS-таргет, затем переустановите поды:
```ruby showLineNumbers title="ios/Podfile"
use_frameworks! :linkage => :dynamic
```
```bash showLineNumbers
cd ios && pod install --repo-update
```
Если ранее вы подключали `Adapty`, `AdaptyUI` или `AdaptyPlugin` как зависимости CocoaPods, сначала удалите все явные строки `pod 'Adapty'`, `pod 'AdaptyUI'` или `pod 'AdaptyPlugin'` из вашего `Podfile`.
:::warning
Переход со статической компоновки по умолчанию на динамические фреймворки может конфликтовать с библиотеками, которые ещё не поддерживают модульные заголовки, и несовместим с Flipper. Если возникнут ошибки сборки, ознакомьтесь с этим [материалом об интеграции Swift Package Manager с библиотеками React Native](https://www.callstack.com/blog/integrating-swift-package-manager-with-react-native-libraries).
:::
Полная инструкция по установке — в разделе [Установка Adapty SDK](sdk-installation-reactnative).
## Получение флоу \{#fetching-flows\}
### getPaywall → getFlow
Тип возвращаемого значения изменился с `AdaptyPaywall` на `AdaptyFlow`, а параметр `locale` убран — при рендеринге флоу локаль определяется автоматически; для кастомных пейволов все локали возвращаются в `flow.remoteConfigs`:
```diff showLineNumbers
- const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
```
`getPaywallForDefaultAudience` переименован аналогично:
```diff showLineNumbers
- const paywall = await adapty.getPaywallForDefaultAudience('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlowForDefaultAudience('YOUR_PLACEMENT_ID');
```
### getPaywallProducts(paywall) → getPaywallProducts(flow)
`getPaywallProducts` сохраняет своё название, но теперь принимает `AdaptyFlow`:
```diff showLineNumbers
- const products = await adapty.getPaywallProducts(paywall);
+ const products = await adapty.getPaywallProducts(flow);
```
## Модель данных \{#data-model\}
`getFlow` возвращает `AdaptyFlow` вместо `AdaptyPaywall`, и структура объекта изменилась:
| поле v3 `AdaptyPaywall` | поле v4 `AdaptyFlow` | Действие |
|---|---|---|
| `remoteConfig?` (одно) | `remoteConfigs?: AdaptyRemoteConfig[]` (массив) | Флоу содержит один Remote Config на каждый настроенный язык. Читайте тот, который соответствует пользователю: `flow.remoteConfigs?.find((c) => c.lang === 'en')`. |
| `products` | `flow.paywalls[i].productIdentifiers` | Идентификаторы продуктов теперь хранятся в каждом варианте флоу, а не в самом флоу. |
| `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Перенесено из флоу в каждый вариант пейвола. |
| `version?: number` | `flowVersionId?: string` | Переименовано, тип изменён с `number` на `string`. |
| `hasViewConfiguration` | удалено | Удалите все проверки `hasViewConfiguration` из кода. |
| `requestLocale` | удалено | Локаль больше не является частью модели. |
| _(новое)_ | `paywalls: AdaptyFlowPaywall[]` | Каждый элемент — один вариант пейвола во флоу. |
| _(новое)_ | `responseCreatedAt: number` | Временная метка ответа сервера в миллисекундах. |
Product identifiers moved from the flow to each variation:
```diff showLineNumbers
- const ids = paywall.products;
+ const ids = flow.paywalls[0].productIdentifiers;
```
## Методы веб-пейвола \{#web-paywall-methods\}
`openWebPaywall` и `createWebPaywallUrl` сохраняют свои названия, но первым аргументом теперь передаётся `AdaptyFlowPaywall` (вариант флоу) вместо `AdaptyPaywall`. По-прежнему можно передать `AdaptyPaywallProduct`.
```diff showLineNumbers
const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
- await adapty.openWebPaywall(paywall);
+ await adapty.openWebPaywall(flow.paywalls[0]);
```
## Отслеживание просмотров флоу \{#tracking-flow-views\}
### logShowPaywall → logShowFlow
`logShowPaywall` переименован в `logShowFlow` и теперь принимает `AdaptyFlow`. Событие по-прежнему логируется для той же вариации, так что существующие метрики воронки и A/B-тестов продолжат работать без изменений в дашборде.
```diff showLineNumbers
- await adapty.logShowPaywall(paywall);
+ await adapty.logShowFlow(flow);
```
Как и в v3, вызывать этот метод при отображении флоу или пейволов, отрисованных с помощью [Flow Builder](adapty-flow-builder) или [Paywall Builder](adapty-paywall-builder), не нужно — Adapty отслеживает такие просмотры автоматически.
## Отображение флоу \{#displaying-flows\}
### createPaywallView → createFlowView
Переименуйте фабричную функцию и передайте `AdaptyFlow`. Методы возвращаемого контроллера (`present`, `dismiss`, `setEventHandlers`, `showDialog`) остаются без изменений:
```diff showLineNumbers
- import { createPaywallView } from 'react-native-adapty';
+ import { createFlowView } from 'react-native-adapty';
- const view = await createPaywallView(paywall);
+ const view = await createFlowView(flow);
await view.present();
```
### AdaptyPaywallView → AdaptyFlowView
Если вы используете React-компонент, переименуйте его и передайте проп `flow`:
```diff showLineNumbers
- import { AdaptyPaywallView } from 'react-native-adapty';
+ import { AdaptyFlowView } from 'react-native-adapty';
- ```diff showLineNumbers - subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; ``` 2. [AdaptySubscriptionDetails](https://react-native.adapty.io/interfaces/adaptysubscriptiondetails): - `promotionalOffer` удалён. Теперь promotional offer передаётся в свойстве `offer` только если он доступен. В этом случае `offer?.identifier?.type` будет равен `'promotional'`. - `introductoryOfferEligibility` удалён (офферы возвращаются только если пользователь имеет право на них). - `offerId` удалён. ID оффера теперь хранится в `AdaptySubscriptionOffer.identifier`. - `offerTags` перемещён в `AdaptySubscriptionOffer.android`.
```diff showLineNumbers - introductoryOffers?: AdaptyDiscountPhase[]; + offer?: AdaptySubscriptionOffer; ios?: { - promotionalOffer?: AdaptyDiscountPhase; subscriptionGroupIdentifier?: string; }; android?: { - offerId?: string; basePlanId: string; - introductoryOfferEligibility: OfferEligibility; - offerTags?: string[]; renewalType?: 'prepaid' | 'autorenewable'; }; } ``` 3. [AdaptyDiscountPhase](https://react-native.adapty.io/interfaces/adaptydiscountphase): - Поле `identifier` удалено из модели `AdaptyDiscountPhase`. Идентификатор оффера теперь хранится в `AdaptySubscriptionOffer.identifier`.
```diff showLineNumbers - ios?: { - readonly identifier?: string; - }; ``` ### Удалённые модели \{#remove-models\} 1. `AttributionSource`: - Вместо него теперь используется строка там, где ранее применялся `AttributionSource`. 2. `OfferEligibility`: - Эта модель удалена, так как больше не нужна. Теперь оффер возвращается только если пользователь имеет право на его получение. ## Удаление метода `getProductsIntroductoryOfferEligibility` \{#remove-getproductsintroductoryoffereligibility-method\} До Adapty SDK 3.3.1 объекты продуктов всегда включали офферы, даже если пользователь не имел права на их получение. Это требовало ручной проверки права на получение оффера перед его использованием. Начиная с версии 3.3.1, объект продукта включает офферы только если пользователь имеет на них право. Это упрощает процесс: если оффер присутствует, можно считать, что пользователь имеет право на его получение. ## Обновление процесса покупки \{#update-making-purchase\} В более ранних версиях отменённые и ожидающие покупки считались ошибками и возвращали коды `2: 'paymentCancelled'` и `25: 'pendingPurchase'` соответственно. Начиная с версии 3.3.1, отменённые и ожидающие покупки считаются успешными результатами и должны обрабатываться соответствующим образом: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` ## Обновление отображения пейволов Paywall Builder \{#update-paywall-builder-paywall-presentation\} Актуальные примеры смотрите в документации [Отображение новых пейволов Paywall Builder в React Native](react-native-present-paywalls). ```diff showLineNumbers - import { createPaywallView } from '@adapty/react-native-ui'; + import { createPaywallView } from 'react-native-adapty/dist/ui'; const view = await createPaywallView(paywall); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` ## Обновление реализации таймеров, определяемых разработчиком \{#update-developer-defined-timer-implementation\} Переименуйте параметр `timerInfo` в `customTimers`: ```diff showLineNumbers - let timerInfo = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } + let customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } //and then you can pass it to createPaywallView as follows: - view = await createPaywallView(paywall, { timerInfo }) + view = await createPaywallView(paywall, { customTimers }) ``` ## Изменение событий покупки в Paywall Builder \{#modify-paywall-builder-purchase-events\} Раньше: - Отменённые покупки вызывали коллбэк `onPurchaseCancelled`. - Ожидающие покупки возвращали код ошибки `25: 'pendingPurchase'`. Теперь: - Оба случая обрабатываются коллбэком `onPurchaseCompleted`. #### Шаги для миграции: \{#steps-to-migrate\} 1. Удалите коллбэк `onPurchaseCancelled`. 2. Удалите обработку кода ошибки `25: 'pendingPurchase'`. 3. Обновите коллбэк `onPurchaseCompleted`: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ // ... other optional callbacks onPurchaseCompleted(purchaseResult, product) { switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; // highlight-start case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; // highlight-end } // highlight-start return purchaseResult.type !== 'user_cancelled'; // highlight-end }, }); ``` ## Обновление событий кастомных действий в Paywall Builder \{#modify-paywall-builder-custom-action-events\} Удалённые коллбэки: - `onAction` - `onCustomEvent` Добавленный коллбэк: - Новый коллбэк `onCustomAction(actionId)`. Используйте его для кастомных действий. ## Изменение коллбэка `onProductSelected` \{#modify-onproductselected-callback\} Ранее `onProductSelected` принимал объект `product`. Теперь требуется `productId` в виде строки. ## Удаление параметров сторонних интеграций из метода `updateProfile` \{#remove-third-party-integration-parameters-from-updateprofile-method\} Идентификаторы сторонних интеграций теперь задаются с помощью метода `setIntegrationIdentifier`. Метод `updateProfile` больше не принимает их. ## Обновление конфигурации SDK сторонних интеграций \{#update-third-party-integration-sdk-configuration\} Чтобы интеграции корректно работали с Adapty React Native SDK 3.3.1 и выше, обновите конфигурации SDK для следующих интеграций согласно разделам ниже. Кроме того, если вы использовали `AttributionSource` для получения идентификатора атрибуции, измените код так, чтобы передавать нужный идентификатор в виде строки. ### Adjust Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с Adjust](adjust#connect-your-app-to-adjust). ```diff showLineNumbers import { Adjust, AdjustConfig } from "react-native-adjust"; import { adapty } from "react-native-adapty"; var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); + Adjust.getAdid((adid) => { + if (adid) + adapty.setIntegrationIdentifier("adjust_device_id", adid); + }); ``` ### AirBridge \{#airbridge\} Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Конфигурация SDK для интеграции AirBridge](airbridge#connect-your-app-to-airbridge). ```diff showLineNumbers import Airbridge from 'airbridge-react-native-sdk'; import { adapty } from 'react-native-adapty'; try { const deviceId = await Airbridge.state.deviceUUID(); - await adapty.updateProfile({ - airbridgeDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` ### Amplitude \{#amplitude\} Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Конфигурация SDK для интеграции Amplitude](amplitude#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; try { - await adapty.updateProfile({ - amplitudeDeviceId: deviceId, - amplitudeUserId: userId, - }); + await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); + await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` ### AppMetrica Обновите код своего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [Настройка SDK для интеграции с AppMetrica](appmetrica#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import AppMetrica, { DEVICE_ID_KEY, StartupParams, StartupParamsReason } from '@appmetrica/react-native-analytics'; // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceId = params?.deviceId if (deviceId) { try { - await adapty.updateProfile({ - appmetricaProfileId: 'YOUR_ADAPTY_CUSTOMER_USER_ID', - appmetricaDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); + await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_KEY]) ``` ### AppsFlyer Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Настройка SDK для интеграции с AppsFlyer](appsflyer#connect-your-app-to-appsflyer). ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import appsFlyer from 'react-native-appsflyer'; appsFlyer.onInstallConversionData(installData => { try { - const networkUserId = appsFlyer.getAppsFlyerUID(); - adapty.updateAttribution(installData, AttributionSource.AppsFlyer, networkUserId); + const uid = appsFlyer.getAppsFlyerUID(); + adapty.setIntegrationIdentifier("appsflyer_id", uid); + adapty.updateAttribution(installData, "appsflyer"); } catch (error) { // handle the error } }); // ... appsFlyer.initSdk(/*...*/); ``` ### Branch \{#branch\} Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Конфигурация SDK для интеграции Branch](branch#connect-your-app-to-branch). ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { - adapty.updateAttribution(params, AttributionSource.Branch); + adapty.updateAttribution(params, "branch"); }, }); ``` ### Facebook Ads Обновите код вашего мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [Настройка SDK для интеграции с Facebook Ads](facebook-ads#connect-your-app-to-facebook-ads). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { AppEventsLogger } from 'react-native-fbsdk-next'; try { const anonymousId = await AppEventsLogger.getAnonymousID(); - await adapty.updateProfile({ - facebookAnonymousId: anonymousId, - }); + await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` ### Firebase и Google Analytics \{#firebase-and-google-analytics\} Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [настройка SDK для интеграции с Firebase и Google Analytics](firebase-and-google-analytics). ```diff showLineNumbers import analytics from '@react-native-firebase/analytics'; import { adapty } from 'react-native-adapty'; try { const appInstanceId = await analytics().getAppInstanceId(); - await adapty.updateProfile({ - firebaseAppInstanceId: appInstanceId, - }); + await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } catch (error) { // handle `AdaptyError` } ``` ### Mixpanel \{#mixpanel\} Обновите код мобильного приложения, как показано ниже. Полный пример кода смотрите в разделе [Конфигурация SDK для интеграции Mixpanel](mixpanel#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { Mixpanel } from 'mixpanel-react-native'; // ... try { - await adapty.updateProfile({ - mixpanelUserId: mixpanelUserId, - }); + await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` ### OneSignal Обновите код мобильного приложения, как показано ниже. Полный пример кода можно найти в разделе [Настройка SDK для интеграции с OneSignal](onesignal#sdk-configuration).