SlideShare a Scribd company logo
App Store Subscriptions
Condensed Edition
Mark Pavlidis

mark@pavlidis.ca 

mark@groksoftware.net

@mhp

TACOW Presentation 

2019-05-14
Agenda
Why: Choose a Subscription Business Model?

Who: Am I To Know?

What: You need to know to get started?

How: Do you avoid some pain points?

Where: Are we having beers?
Why Choose Subscriptions?
• Fastest growing business model
on the App Store

• Over a 80% of all apps are free,
up from 67% in 2014

• Generated $10B in revenue in
2017, estimated $75B in 2022
App Store Revenue (%)
0
20
40
60
80
100
2010 2012 2015 2018
Paid Free+IAP Free+Subscrption
Why Choose Subscriptions?
Why Choose Subscriptions?
Why Choose Subscriptions?
PAID SUBSCRIPTION
Periodic impulse in revenue
Slow build to the sum of
the impulses every 3-4
months recurring
Launch
Apple Design Award
App Store Feature
Why Choose Subscriptions?
• Recurring Revenue
• Higher price points and fewer customers

• “Build meaningful relationships” with good customers

• Don’t hold back big features for new major versions

• Apple said so

• Everybody is doing it
Why Choose Subscriptions?
Are subscriptions right for me?

• Offering ongoing value

• Is the model right for the potential customers

• Do you have ongoing infrastructure costs

Popular Categories:

• Content, Utilities, Dating, Productivity, Creative
Who Am I To Know?
• First implemented Non-Renewing Subscriptions in 2011















Who Am I To Know?
• First implemented Non-Renewable Subscriptions in 2011

• Auto-renewing plans for Flixel hosting service in 2014

• Included the app unlock in 2015 before it was “legal”

• Worked around a number of limitations that have since been
added to the App Store (i.e., price changes)

• Lucky for you there are still lots of limitations and workarounds
What Are The Basics
• Create your Auto-renewing plans in App Store Connect

• Initiate StoreKit at launch and fetch products

• Show localized plans in-app with the conspicuous disclaimer

• ALWAYS END YOUR TRANSACTIONS

• Provide a mechanism to restore subscription and non-
consumable IAPs
Create Auto-Renewing IAP
Create Auto-Renewing IAP
Create Subscription Group
Subscription Groups
• Made up of subscriptions of different levels and durations

• Helps ensure multiple subscriptions are not active

• Rank the subscriptions in descending order by most access

• Ranking defines rules for upgrade, crossgrade, downgrade
Subscription Groups
Initiate StoreKit
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
PurchaseController.shared.setup()
return true
}
Initiate StoreKit
class PurchaseController: NSObject {
func setup() {
// Register Observer
SKPaymentQueue.default().add(self)
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions
transactions: [SKPaymentTransaction]) {
//Handle transaction states here.
}
}
Fetch Products
func setup() {
// Register Observer
SKPaymentQueue.default().add(self)
// Register for product refresh
refreshObserver =
NotificationCenter.default.addObserver(forName:
UIApplication.didBecomeActiveNotification, object: nil,
queue: .main) { [weak self] note in
self?.fetchProducts()
}
}
Fetch Products
func fetchProducts() {
guard productsRequest == nil else { return }
//
productsRequest = SKProductsRequest(productIdentifiers:
productIdentifiers)
productsRequest?.delegate = self
productsRequest?.start()
}
}
extension PurchaseController: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive
response: SKProductsResponse) {
products = response.products
}
}
Localized Pricing
open class SKProduct : NSObject {
@available(iOS 3.0, *)
open var localizedDescription: String { get }
@available(iOS 3.0, *)
open var localizedTitle: String { get }
@available(iOS 3.0, *)
open var price: NSDecimalNumber { get }
@available(iOS 3.0, *)
open var priceLocale: Locale { get }
Localized Pricing
extension SKProduct {
/// - returns: The cost of the product formatted in the local
currency.
var regularPrice: String? {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = self.priceLocale
return formatter.string(from: self.price)
}
}
Display Localized Products
Conspicuous Disclaimer
Start Purchase
func purchase(_ product: SKProduct) {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
Purchase Completes
• Once the transaction state changes to .purchased you can
store the subscription transaction to unlock
• What about if a renewal occurs?

• What if the user deletes the app?

• What if you have more than one app or a web service?

• Can use the receipt instead of restoring the transactions
Complete Transactions
• Once verified on-device or sent the receipt to your server call 



SKPaymentQueue.default().finishTransaction(_:)
• If you don’t StoreKit will keep posting the transaction

• Apple is more likely to refund the transaction if you don’t
let receiptURL = Bundle.main.appStoreReceiptURL
• Receipt is in PKCS Cryptographic Container & ASN.1 encoded 

• Need to build a static OpenSSL, asn1c, etc to verify it

• Bundle Apple Root CA Certificate 

• Not provided by Apple on purpose — no single point of failure
On-Device Receipt Validation
Server Side Receipt Validation
• If you can, have your server manage receipt verification 

• Send the BASE64 binary encoded receipt data and store it

• Server sends it to Apple server that responds with JSON
payload of the receipt and a latest version of receipt data

• JSON includes additional information about subscription state
Server Side Receipt Validation
• If you have multiple apps/platforms you must use this method

• App Transport Security is required

• Different endpoints for Production and Sandbox environments

https://buy.itunes.apple.com/verifyReceipt

https://sandbox.itunes.apple.com/verifyReceipt

• Don’t call from the device

• Status code to indicate if you should use the other environment
Additional Receipt Fields
• auto_renew_status indicates if the customer has cancelled

• auto_renew_product_id renewal product could be different

• price_consent_status when you change the price 

• is_in_billing_retry_period indicate past due to user 

• expiration_intent is voluntary, billing, price increase, etc.

• original_transaction_id your primary key to the subscription
JSON Receipt Demo
Managing Server-to-Server
• Your server can receive push subscription status updates

• General App Information > Subscription Status URL

• Only one endpoint, so you have to forward sandbox requests 

• Different data structure containing partial change data

• Delivery is not guaranteed 

• Poll all receipts daily to ensure auto-renewal and cancelations are
synchronized
Ways to Increase Conversions
• Promoted In-App Purchases

• Auto-renewing Subscription Offers

• Introductory Offers

• NEW: Promotional Offers

• Handling Past Due user experience
Promoted IAPs
• Can promote up to 20 IAPs

• Give customers browsing the App Store a one-tap buy button

• Needs unique images

• Shows up in search results (n.b., ASO marketers)

• Another reason you need to initialize StoreKit at launch
Promoted IAPs
func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment
payment: SKPayment, for product: SKProduct) -> Bool
• Always return false now or risk rejection

• Hold on to the SKPayment

• Display Product, PRICE, and Conspicuous Disclaimer 

• Have the user sign-in/up if necessary

• Then add the payment to the payment queue
Subscription Offers
Introductory Offers
• Free Trial, Pay as you go, Pay up front

• Unique by (Territory, Plan)

• Displayed on Promoted IAP on the App Store

• SKProduct.introductoryPrice
Subscription Offers
Subscription Offers
Promotional Offers
• Up to 10 offers per plan to existing or churned subscribers

• You decide which are shown

• Not displayed on the App Store — avoid IAP pollution 

• Requires a server to determine eligibility & generate signature 

• SKProduct.discounts
Past Due User Experience
• On-device or before last year you don’t know user is past due

• Apple used to cancel after 24 hours, now it is 60 days

• Up to you how to limit access

• Clearly inform the user that they are past due

• Show a button that opens 

https://apps.apple.com/account/billing
How Do You Avoid Some Pain
• Cancelled is not what you think it means

• Converting a Paid app to Free+Subscription

• New App Auto-Renewing Subscription Propagation

• Have I mentioned the Conspicuous Disclaimer?
What “Cancelled” Means
• Another reason to poll nightly is that a transaction in the receipt
can change

• cancellation_date_ms, cancellation_reason
• Means refunded and you should remove access immediately
REALLY ?
How To Know If Churned
• On-device: if the latest transaction in the receipt end date is in
the past now

• Server-side : check pending_renewal_info for
expiration_intent
Converting Paid to Subscription
Converting Paid to Subscription
Sandbox
Prod iOS
Prod macOS
REALLY ?
New App with Subscriptions
• Turns out that auto-renewing subscriptions aren’t added to the
production environment until the app is live

• Most of the time this propagates to all stores quickly

• But…
New App with Subscriptions
Activation of the In-App Purchase identifiers may lag up to 48
hours following the activation of the application
REALLY ?
Conspicuous Disclaimer
Summary
Why: Choose a Subscription Business Model?

Who: Am I To Know?

What: You need to know to get started?

How: Do you avoid some pain points?
Available for consulting after
WWDC
References
• Auto-renewable Subscriptions

• In-App Purchase and Subscriptions

• Implementing Introductory Offers in Your App

• Implementing Subscription Offers

• IAP Propagation Critical Bug “Tech Note”
App Store Subscriptions
Condensed Edition
Mark Pavlidis

mark@pavlidis.ca 

mark@groksoftware.net

@mhp

TACOW Presentation 

2019-05-14

More Related Content

Similar to App Store Subscriptions - Condensed Edition

Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2
Yanzer Lee
 
GRO n GO
GRO n GO GRO n GO
GRO n GO
hetvi naik
 
SAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work LoadSAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work Load
anjalirao366
 
Shopify
ShopifyShopify
Shopify
Nascenia IT
 
In-App Purchase
In-App PurchaseIn-App Purchase
In-App Purchase
Max Stottrop
 
Proposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management SystemsProposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management Systems
MacWolf1
 
New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...
Jade Global
 
Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016
Neil Lasrado
 
How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?
PeppyOcean
 
What's New in Acumatica 5.0
What's New in Acumatica 5.0What's New in Acumatica 5.0
What's New in Acumatica 5.0
Gabriel Michaud
 
KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013
matteopanfilo
 
Different architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retailDifferent architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retail
Sonny56
 
Maximizing QuickBooks
Maximizing QuickBooksMaximizing QuickBooks
Maximizing QuickBooks
Lean Teams
 
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie GibsonNCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
Archersan
 
Subsription and Recurring Payments
Subsription and Recurring PaymentsSubsription and Recurring Payments
Subsription and Recurring PaymentsAli Memon
 
Cool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express CheckoutCool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express Checkout
PayPalX Developer Network
 
How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)
Lean Teams
 
Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables
KPIT
 

Similar to App Store Subscriptions - Condensed Edition (20)

Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2
 
GRO n GO
GRO n GO GRO n GO
GRO n GO
 
SAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work LoadSAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work Load
 
Shopify
ShopifyShopify
Shopify
 
In-App Purchase
In-App PurchaseIn-App Purchase
In-App Purchase
 
Proposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management SystemsProposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management Systems
 
New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...
 
Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016
 
How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?
 
What's New in Acumatica 5.0
What's New in Acumatica 5.0What's New in Acumatica 5.0
What's New in Acumatica 5.0
 
KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013
 
Different architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retailDifferent architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retail
 
AP and AR Positioning
AP and AR PositioningAP and AR Positioning
AP and AR Positioning
 
Maximizing QuickBooks
Maximizing QuickBooksMaximizing QuickBooks
Maximizing QuickBooks
 
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie GibsonNCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
 
Subsription and Recurring Payments
Subsription and Recurring PaymentsSubsription and Recurring Payments
Subsription and Recurring Payments
 
Cool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express CheckoutCool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express Checkout
 
How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)
 
Company preso
Company presoCompany preso
Company preso
 
Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables
 

Recently uploaded

Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Nidhi Software Price. Fact , Costs, Tips
Nidhi Software Price. Fact , Costs, TipsNidhi Software Price. Fact , Costs, Tips
Nidhi Software Price. Fact , Costs, Tips
vrstrong314
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
Game Development with Unity3D (Game Development lecture 3)
Game Development  with Unity3D (Game Development lecture 3)Game Development  with Unity3D (Game Development lecture 3)
Game Development with Unity3D (Game Development lecture 3)
abdulrafaychaudhry
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
abdulrafaychaudhry
 

Recently uploaded (20)

Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Nidhi Software Price. Fact , Costs, Tips
Nidhi Software Price. Fact , Costs, TipsNidhi Software Price. Fact , Costs, Tips
Nidhi Software Price. Fact , Costs, Tips
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
Game Development with Unity3D (Game Development lecture 3)
Game Development  with Unity3D (Game Development lecture 3)Game Development  with Unity3D (Game Development lecture 3)
Game Development with Unity3D (Game Development lecture 3)
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
 

App Store Subscriptions - Condensed Edition

  • 1. App Store Subscriptions Condensed Edition Mark Pavlidis mark@pavlidis.ca mark@groksoftware.net @mhp TACOW Presentation 2019-05-14
  • 2. Agenda Why: Choose a Subscription Business Model? Who: Am I To Know? What: You need to know to get started? How: Do you avoid some pain points? Where: Are we having beers?
  • 3. Why Choose Subscriptions? • Fastest growing business model on the App Store • Over a 80% of all apps are free, up from 67% in 2014 • Generated $10B in revenue in 2017, estimated $75B in 2022 App Store Revenue (%) 0 20 40 60 80 100 2010 2012 2015 2018 Paid Free+IAP Free+Subscrption
  • 6. Why Choose Subscriptions? PAID SUBSCRIPTION Periodic impulse in revenue Slow build to the sum of the impulses every 3-4 months recurring Launch Apple Design Award App Store Feature
  • 7. Why Choose Subscriptions? • Recurring Revenue • Higher price points and fewer customers • “Build meaningful relationships” with good customers • Don’t hold back big features for new major versions • Apple said so • Everybody is doing it
  • 8. Why Choose Subscriptions? Are subscriptions right for me? • Offering ongoing value • Is the model right for the potential customers • Do you have ongoing infrastructure costs Popular Categories: • Content, Utilities, Dating, Productivity, Creative
  • 9. Who Am I To Know? • First implemented Non-Renewing Subscriptions in 2011
 
 
 
 
 
 
 

  • 10.
  • 11. Who Am I To Know? • First implemented Non-Renewable Subscriptions in 2011 • Auto-renewing plans for Flixel hosting service in 2014 • Included the app unlock in 2015 before it was “legal” • Worked around a number of limitations that have since been added to the App Store (i.e., price changes) • Lucky for you there are still lots of limitations and workarounds
  • 12. What Are The Basics • Create your Auto-renewing plans in App Store Connect • Initiate StoreKit at launch and fetch products • Show localized plans in-app with the conspicuous disclaimer • ALWAYS END YOUR TRANSACTIONS • Provide a mechanism to restore subscription and non- consumable IAPs
  • 16. Subscription Groups • Made up of subscriptions of different levels and durations • Helps ensure multiple subscriptions are not active • Rank the subscriptions in descending order by most access • Ranking defines rules for upgrade, crossgrade, downgrade
  • 18. Initiate StoreKit func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { PurchaseController.shared.setup() return true }
  • 19. Initiate StoreKit class PurchaseController: NSObject { func setup() { // Register Observer SKPaymentQueue.default().add(self) } func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { //Handle transaction states here. } }
  • 20. Fetch Products func setup() { // Register Observer SKPaymentQueue.default().add(self) // Register for product refresh refreshObserver = NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] note in self?.fetchProducts() } }
  • 21. Fetch Products func fetchProducts() { guard productsRequest == nil else { return } // productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers) productsRequest?.delegate = self productsRequest?.start() } } extension PurchaseController: SKProductsRequestDelegate { func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { products = response.products } }
  • 22. Localized Pricing open class SKProduct : NSObject { @available(iOS 3.0, *) open var localizedDescription: String { get } @available(iOS 3.0, *) open var localizedTitle: String { get } @available(iOS 3.0, *) open var price: NSDecimalNumber { get } @available(iOS 3.0, *) open var priceLocale: Locale { get }
  • 23. Localized Pricing extension SKProduct { /// - returns: The cost of the product formatted in the local currency. var regularPrice: String? { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = self.priceLocale return formatter.string(from: self.price) } }
  • 26. Start Purchase func purchase(_ product: SKProduct) { let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) }
  • 27. Purchase Completes • Once the transaction state changes to .purchased you can store the subscription transaction to unlock • What about if a renewal occurs? • What if the user deletes the app? • What if you have more than one app or a web service? • Can use the receipt instead of restoring the transactions
  • 28. Complete Transactions • Once verified on-device or sent the receipt to your server call 
 
 SKPaymentQueue.default().finishTransaction(_:) • If you don’t StoreKit will keep posting the transaction • Apple is more likely to refund the transaction if you don’t
  • 29. let receiptURL = Bundle.main.appStoreReceiptURL • Receipt is in PKCS Cryptographic Container & ASN.1 encoded • Need to build a static OpenSSL, asn1c, etc to verify it • Bundle Apple Root CA Certificate • Not provided by Apple on purpose — no single point of failure On-Device Receipt Validation
  • 30. Server Side Receipt Validation • If you can, have your server manage receipt verification • Send the BASE64 binary encoded receipt data and store it • Server sends it to Apple server that responds with JSON payload of the receipt and a latest version of receipt data • JSON includes additional information about subscription state
  • 31. Server Side Receipt Validation • If you have multiple apps/platforms you must use this method • App Transport Security is required • Different endpoints for Production and Sandbox environments https://buy.itunes.apple.com/verifyReceipt
 https://sandbox.itunes.apple.com/verifyReceipt • Don’t call from the device • Status code to indicate if you should use the other environment
  • 32. Additional Receipt Fields • auto_renew_status indicates if the customer has cancelled • auto_renew_product_id renewal product could be different • price_consent_status when you change the price • is_in_billing_retry_period indicate past due to user • expiration_intent is voluntary, billing, price increase, etc. • original_transaction_id your primary key to the subscription
  • 34. Managing Server-to-Server • Your server can receive push subscription status updates • General App Information > Subscription Status URL • Only one endpoint, so you have to forward sandbox requests • Different data structure containing partial change data • Delivery is not guaranteed • Poll all receipts daily to ensure auto-renewal and cancelations are synchronized
  • 35. Ways to Increase Conversions • Promoted In-App Purchases • Auto-renewing Subscription Offers • Introductory Offers • NEW: Promotional Offers • Handling Past Due user experience
  • 36. Promoted IAPs • Can promote up to 20 IAPs • Give customers browsing the App Store a one-tap buy button • Needs unique images • Shows up in search results (n.b., ASO marketers) • Another reason you need to initialize StoreKit at launch
  • 37. Promoted IAPs func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool • Always return false now or risk rejection • Hold on to the SKPayment • Display Product, PRICE, and Conspicuous Disclaimer • Have the user sign-in/up if necessary • Then add the payment to the payment queue
  • 38.
  • 39. Subscription Offers Introductory Offers • Free Trial, Pay as you go, Pay up front • Unique by (Territory, Plan) • Displayed on Promoted IAP on the App Store • SKProduct.introductoryPrice
  • 41. Subscription Offers Promotional Offers • Up to 10 offers per plan to existing or churned subscribers • You decide which are shown • Not displayed on the App Store — avoid IAP pollution • Requires a server to determine eligibility & generate signature • SKProduct.discounts
  • 42. Past Due User Experience • On-device or before last year you don’t know user is past due • Apple used to cancel after 24 hours, now it is 60 days • Up to you how to limit access • Clearly inform the user that they are past due • Show a button that opens 
 https://apps.apple.com/account/billing
  • 43. How Do You Avoid Some Pain • Cancelled is not what you think it means • Converting a Paid app to Free+Subscription • New App Auto-Renewing Subscription Propagation • Have I mentioned the Conspicuous Disclaimer?
  • 44. What “Cancelled” Means • Another reason to poll nightly is that a transaction in the receipt can change • cancellation_date_ms, cancellation_reason • Means refunded and you should remove access immediately
  • 46. How To Know If Churned • On-device: if the latest transaction in the receipt end date is in the past now • Server-side : check pending_renewal_info for expiration_intent
  • 47. Converting Paid to Subscription
  • 48. Converting Paid to Subscription Sandbox Prod iOS Prod macOS
  • 50. New App with Subscriptions • Turns out that auto-renewing subscriptions aren’t added to the production environment until the app is live • Most of the time this propagates to all stores quickly • But…
  • 51. New App with Subscriptions Activation of the In-App Purchase identifiers may lag up to 48 hours following the activation of the application
  • 54. Summary Why: Choose a Subscription Business Model? Who: Am I To Know? What: You need to know to get started? How: Do you avoid some pain points?
  • 56. References • Auto-renewable Subscriptions • In-App Purchase and Subscriptions • Implementing Introductory Offers in Your App • Implementing Subscription Offers • IAP Propagation Critical Bug “Tech Note”
  • 57. App Store Subscriptions Condensed Edition Mark Pavlidis mark@pavlidis.ca mark@groksoftware.net @mhp TACOW Presentation 2019-05-14