$30 off During Our Annual Pro Sale. View Details »

Building a modern subscription experience on iOS

Bas Broek
August 17, 2022

Building a modern subscription experience on iOS

Sharing a story on how we built subscriptions for the iOS WeTransfer app.

Bas Broek

August 17, 2022
Tweet

More Decks by Bas Broek

Other Decks in Programming

Transcript

  1. BUILDING A MODERN
    SUBSCRIPTION EXPERIENCE
    ON IOS
    @BASTHOMAS
    1 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  2. AMAZING ANNUAL
    RECURRING REVENUE... ON
    IOS
    @BASTHOMAS
    2 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  3. SUPERB SUBSCRIPTIONS... ON
    IOS
    @BASTHOMAS
    3 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  4. INTERESTING IN-APP
    PURCHASES... ON IOS
    @BASTHOMAS
    4 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  5. BUILDING A MODERN
    SUBSCRIPTION EXPERIENCE
    ON IOS
    @BASTHOMAS
    5 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  6. WHO AM I?
    ▸ @basthomas on Twitter
    ▸ XING
    ▸ Moya, GitHawk
    ▸ Apple (macOS VoiceOver)
    ▸ WeTransfer
    6 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  7. WHY AM I TALKING ABOUT
    THIS TOPIC?
    7 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  8. WETRANSFER IOS
    !
    8 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  9. WETRANSFER IOS
    !!
    9 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  10. WETRANSFER IOS
    !!!
    10 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  11. !
    11 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  12. !
    ..?
    12 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  13. !
    13 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  14. !
    14 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  15. WE GOT SOME DESIGNS.
    LET'S GET CRACKIN', RIGHT?
    15 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  16. 16 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  17. ACCESSIBILITY
    17 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  18. 18 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  19. 19 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  20. WAIT, TWITTER?
    20 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  21. !
    21 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  22. HAPTICS
    22 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  23. VOICEOVER
    23 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  24. VOICE CONTROL & FULL
    KEYBOARD ACCESS
    24 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  25. DARK MODE,
    MOTION, MORE
    25 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  26. LET'S GET
    CRACKIN'
    26 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  27. LOCAL
    CONFIGURATION
    27 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  28. 28 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  29. 29 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  30. WE'LL START
    SLOWLY
    30 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  31. ... AND USE
    FEATURE FLAGS
    31 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  32. EVERYTHING'S GOING TO BE
    FINE, RIGHT?
    32 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  33. 33 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  34. 34 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  35. 35 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  36. 36 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  37. public func purchase(product: StoreProduct) async throws -> PurchaseInformation {
    try checkRevenueCatConfiguration()
    let purchaseInformation = try await revenueCat.purchase(product: product)
    return .init(
    transaction: purchaseInformation.0,
    customerInformation: .init(customerInformation: purchaseInformation.1),
    isUserCancelled: purchaseInformation.2
    )
    }
    37 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  38. ... THAT'S IT?
    38 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  39. THANKS,
    REVENUECAT
    39 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  40. OH, AND THEN WE
    CRASHED
    40 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  41. HAS ANYONE EVER TOLD YOU
    TO BE CAREFUL
    WITH FORCE-UNWRAPPING?
    41 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  42. !
    42 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  43. // when we are here, we should always be able
    // to find a package. if not, that's a programmer error
    43 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  44. PRODUCT
    IDENTIFIER: ?
    44 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  45. // when we are here, we should always be able
    // to find a package. if not, that's a
    // programmer error... or an Apple issue.
    // So do _NOT_ crash.
    !
    45 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  46. PRODUCT
    IDENTIFIER:
    46 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  47. ANYWAY...
    47 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  48. DEMO
    48 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  49. 49 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  50. 50 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  51. DEMO
    51 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  52. 52 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  53. 53 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  54. 54 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  55. 55 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  56. EVERYTHING IS GOING (TO
    BE) FINE, RIGHT?
    56 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  57. 57 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  58. GRADUAL
    ROLLOUT
    58 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  59. 59 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  60. 60 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  61. IT'S NOT A BUG,
    IT'S A FEATURE
    61 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  62. YOLO
    62 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  63. YOLO
    CARPE DIEM
    63 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  64. 64 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  65. !"#
    65 — @basthomas, SwiftConf, August 17, 2022

    View Slide


  66. 66 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  67. !
    67 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  68. PAYWALLS
    68 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  69. PAYWALLS
    CONTEXTUAL PAYWALLS
    69 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  70. DEMO
    70 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  71. 71 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  72. CHANGING EXPIRATION
    DATES
    PASSWORD PROTECTION
    TRANSFER LIMIT
    72 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  73. PRE-LOGIN
    PAYWALL
    73 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  74. !
    74 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  75. !
    75 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  76. !
    76 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  77. A NOTE ON CUSTOMER
    SATISFACTION...
    77 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  78. BE CAREFUL WITH "TRICKING"
    USERS TO BUY
    SUBSCRIPTIONS
    78 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  79. DEMO
    79 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  80. 80 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  81. !
    81 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  82. 82 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  83. TICKING LIKE (GERMAN)
    CLOCKWORK
    83 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  84. There's something one should expect not
    only of a watch but also of oneself: to
    never stand sti .
    — Walter Lange
    84 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  85. EXPERIMENTS
    85 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  86. OPTIMIZATION*
    86 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  87. * HAPPY CUSTOMERS >
    SHORT TERM
    87 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  88. OPTIMIZATIONS TO CONSIDER
    ▸ Default to monthly
    ▸ Default to yearly
    ▸ Focus on Pro
    ▸ Focus on Premium
    ▸ Button colors
    ▸ Etc. etc.
    88 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  89. VERIFY, VERIFY,
    VERIFY
    89 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  90. !
    90 — @basthomas, SwiftConf, August 17, 2022

    View Slide

  91. THANK YOU!
    @BASTHOMAS
    91 — @basthomas, SwiftConf, August 17, 2022

    View Slide