A/B-тестирование интерфейса в iOS

В этом сценарии сервер выбирает вариант кнопки перехода к оплате, а приложение рисует его по content.custom?.json. Сначала инициализируйте SDK. Методы выбора контента сами не показывают UI; ограничения автопоказа описаны в Своём UI и Custom JSON.

Для ручного учёта показа отключите неявный impression в Options после инициализации:

GravitySDK.instance.setOptions(
    options: Options(isImplicitImpression: false),
    contentSettings: nil,
    proxyUrl: nil
)

Настройка глобальная. Если приложение уже задаёт ContentSettings или proxyUrl, передайте их здесь вместо nil; остальные Options тоже сохраните явно. Проверьте tracking показов кампании по фактическому ответу сервера.

Подготовьте кампанию

  1. Создайте кампанию в приложении с двумя вариантами и нужным распределением аудитории для A/B-теста.
  2. Настройте кампанию с Custom JSON для selector checkout_button, контекстом CART и location app://cart. Для примера используйте один корневой content без дополнительных шагов (step отсутствует).
  3. В контрольном варианте задайте JSON:
{ "variant": "control", "label": "Перейти к оплате" }
  1. Во втором варианте задайте JSON:
{ "variant": "compact", "label": "Оформить заказ" }
  1. Опубликуйте кампанию. Названия variant и типы полей должны совпадать с моделями приложения. Настройте цель по бизнес-событию checkout-started-v1, которое отправляется при нажатии кнопки.

Приложение не распределяет аудиторию случайным образом: оно использует вариант из ответа сервера. Повторный выбор контента выполняйте при новом открытии размещения или явном обновлении, а не при каждом пересчёте UI.

Получите и проверьте вариант

Добавьте в проект gravity_content.swift и ab_example.swift. Первый файл загружает корневой content и проверяет JSON; второй показывает кнопку и отправляет engagement. Модель принимает только control и compact, непустой label и корректные типы полей.

let cartContext = PageContext(type: .cart, data: [], location: "app://cart")

CheckoutExperimentView(pageContext: cartContext, onCheckout: openCheckout)
    .id(placementKey)

placementKey — Hashable-ключ размещения, которым управляет приложение. Меняйте его при смене контекста, чтобы создать отдельное состояние загрузки. Сам PageContext в iOS SDK имеет Equatable, но не Hashable и не подходит для .id(...).

Fallback

Если нет кампании, запрос завершился ошибкой, JSON повреждён, variant неизвестен или label пуст, показывайте стандартную кнопку приложения. Пример не связывает такой fallback с campaign/content и не отправляет ему impression выбранного варианта.

Не считайте fallback контрольной группой теста: контрольный вариант должен прийти из опубликованной кампании. Сбой выбора контента — отдельное состояние интеграции.

Учтите фактический показ

getContentBySelector автоматически отправляет content load tracking. Это не подтверждение показа кнопки. Пример отправляет ContentImpressionEngagement только после появления UI с успешно разобранным вариантом и сохраняет исходные campaign/content для аналитики.

Показ в примере означает появление компонента в UI, без проверки перекрывающих слоёв. Если нужно учитывать видимость в scroll-контейнере, реализуйте detector и отправляйте ContentVisibleImpressionEngagement по правилам собственного UI. Не отправляйте impression ещё раз из callback загрузки.

При нажатии кнопки отдельно отправляется CustomEvent типа checkout-started-v1 с текущим PageContext. Публичного ContentClickEngagement у native SDK нет. Результат теста оценивайте по выбранной бизнес-цели, а не по числу загрузок JSON.

Проверка

  1. Убедитесь, что оба серверных варианта отображаются с ожидаемым label и отступами.
  2. Проверьте пустой ответ, ошибку сети, неизвестный variant и некорректные типы JSON: стандартный UI должен работать.
  3. Проверьте, что загрузка не учитывается как ручной показ, а повторный пересчёт UI не создаёт новый выбор варианта.
  4. Проверьте бизнес-событие после нажатия и отсутствие impression кампании для fallback.