На WWDC’17 Apple показала обновленный интерфейс App Store и представила ряд нововведений. Среди них были продвигаемые встроенные покупки, которые с выходом iOS 11 будут выводится прямо в поиске и редакторских подборках наряду с приложениями.
В нашем случае это особенно актуальная вещь, так как в текущем проекте War Robots мы используем встроенные покупки, которые для нас стали самым оптимальным способом монетизации. Поэтому в нескольких новых играх, которые сейчас в разработке, мы также собираемся их использовать.
Одно из главных отличий — теперь пользователь сможет совершить встроенную покупку прямо в магазине, после чего будет установлено приложение и информация о покупке будет сообщена при запуске. Для этого делегат SKPaymentTransactionObserver должен реализовать специальный метод:
- (BOOL)paymentQueue:(SKPaymentQueue *)queue
shouldAddStorePayment:(SKPayment *)payment
forProduct:(SKProduct *)product;
Пока в приложении не реализован этот метод, продвигаемые встроенные покупки нельзя будет приобрести из App Store. Но они будут отображены в специальном разделе на странице приложения.
Для того чтобы встроенную покупку сделать продвигаемой, необходимо заполнить специальные метаданные, недавно появившиеся в iTunes Connect: рекламное изображение, заголовок и краткое описание. После прохождения review изменений покупка появится в новом разделе «Продвижение в App Store», где можно в любой момент поменять значения видимости по умолчанию для всех пользователей и их порядок отображения на странице приложения в App Store. Так можно продвигать до 20 встроенных покупок одновременно и неограниченное количество покупок держать в режиме готовности к включению.
Все эти значения видимости и порядка будут использоваться для пользователей, которые еще не установили приложение.
Важнейшей составляющей нововведения становится возможность программно изменять порядок и видимость продвигаемых встроенных покупок. Теперь мы можем подстраиваться под каждого пользователя приложения: выводить в топ горсть кристаллов игроку, у которого они на нуле; предлагать премиум-аккаунт активному пользователю; или открывать новый уровень игроку, который прошел весь основной контент. Или же вообще сделать специальное очень выгодное предложение покупки премиум-валюты видимым игроку только в тот момент, когда он столкнулся с острой нехваткой ресурсов, но при этом не воспользовался основным предложением по ее приобретению. Можно устроить A/B тестирование для нахождения оптимального порядка.
А конкретнее?
Рассмотрим новые методы API, предоставляемые Apple для совершения данных манипуляций.
Сделаем продвигаемыми две встроенные покупки приложения. До установки и после запуска, если ничего не делать, они будут отображаться у пользователя в соответствии с настройками из iTunes Connect:
Чтобы изменить порядок и видимость этих покупок, нам нужно получить объекты покупок по их sku через SKProductsRequest:
- (void)requestProducts
{
SKProductsRequest* productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"gold.iap.example.com"]];
productRequest.delegate = self;
[productRequest start];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray<SKProduct *>* products = response.products;
// do some stuff
}
Действия с продвигаемыми покупками делаются через SKProductStorePromotionController, который будет реализован в версии iOS 11. Поэтому дальнейшие вызовы оборачиваем проверкой на доступность этой версии. Методов всего четыре, выполнять их можно в любой момент, когда приложение запущено. Рассмотрим каждый из них.
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
if (@available(iOS 11.0, *)) {
NSArray<SKProduct *>* products = response.products;
[[SKProductStorePromotionController defaultController] updateStorePromotionOrder:products completionHandler:^(NSError * _Nullable error) {
if(error != nil) {
NSLog(@"Update store promotion order failed with error: %@", [error description]);
} else {
NSLog(@"Success");
}
}];
} else {
// Fallback on earlier versions
}
}
После выполнения закроем и заново откроем страницу приложения в магазине, и взглянем на раздел встроенных покупок:
Порядок изменился. Данным вызовом мы установили приоритет для товара gold.iap.example.com. Теперь он показывается первым.
Если бы мы передали несколько товаров, они бы отображались в том порядке, в котором мы их передали. Далее идут остальные товары в их порядке по-умолчанию (то есть заданном в iTunes Connect). Если в качестве списка товаров передать nil, переопределение сбросится и все товары вернутся в первоначальное положение. Получить текущий установленный порядок можно вызовом:
- (void)fetchPromotionOrder
{
if (@available(iOS 11.0, *)) {
[[SKProductStorePromotionController defaultController] fetchStorePromotionOrderWithCompletionHandler:^(NSArray<SKProduct *> * _Nonnull storePromotionOrder, NSError * _Nullable error) {
if(error != nil) {
NSLog(@"Fetch store promotion order failed with error: %@", [error description]);
} else {
NSMutableString* productIds = [NSMutableString string];
for (SKProduct* product in storePromotionOrder) {
[productIds appendString:product.productIdentifier];
[productIds appendString:@"; "];
}
NSLog(@"Got promotion order: %@", productIds);
}
}];
} else {
// Not supported
}
}
Метод вернет только те товары, порядок которых был переопределен, в порядке их переопределения.
Другая доступная пара методов взаимодействует с видимостью товаров. Выполнив следующий код мы переопределим видимость переданного товара gold.iap.example.com (в этих методах передается только один товар):
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
if (@available(iOS 11.0, *)) {
SKProduct* product = [response.products objectAtIndex:0];
[[SKProductStorePromotionController defaultController] updateStorePromotionVisibility:SKProductStorePromotionVisibilityHide forProduct:product completionHandler:^(NSError * _Nullable error) {
if(error != nil) {
NSLog(@"Update store promotion visibility failed with error: %@", [error description]);
} else {
NSLog(@"Success");
}
}];
} else {
// Fallback on earlier versions
}
}
Наш приоритетный товар исчез из списка на странице магазина.
Другим методом можно получить текущую установленную видимость товара:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
if (@available(iOS 11.0, *)) {
SKProduct* product = [response.products objectAtIndex:0];
[[SKProductStorePromotionController defaultController] fetchStorePromotionVisibilityForProduct:product completionHandler:^(SKProductStorePromotionVisibility storePromotionVisibility, NSError * _Nullable error) {
if(error != nil) {
NSLog(@"Fetch store promotion visibility failed with error: %@", [error description]);
} else {
NSLog(@"Promotion visibility %ld", (long)storePromotionVisibility);
}
}];
} else {
// Fallback on earlier versions
}
}
Enum SKProductStorePromotionVisibility имеет следующие доступные значения: Show (товар виден), Hide (товар скрыт), Default (значение видимости берется из iTunes Connect).
Таким образом, список встроенных покупок можно подстраивать для каждого конкретного пользователя как угодно. Инструмент — в руках разработчика, остается самое главное: продумать правила показа, ведь именно от них зависит успех продаж тех или иных встроенных покупок и доход от приложения в целом. Все это демонстрирует желание Apple сделать App Store настоящим местом для покупок, а не банальным сервисом для хранения и поиска приложений.
Ссылка на документацию от Apple: developer.apple.com/app-store/promoting-in-app-purchases
Автор: Андрей Грузинов