Tuesday, April 30, 2024
HomeIOS DevelopmentConstructing a backend-driven paywall with RevenueCat – Donny Wals

Constructing a backend-driven paywall with RevenueCat – Donny Wals


On of app growth’s largest downsides (in my view) is that it’s frustratingly onerous for builders to rapidly iterate on an app’s core options because of the App Assessment course of which might take wherever between a number of hours to a couple days.

Because of this course of, builders both must ship their apps with A/B testing in-built in the event that they wish to take a look at a number of variations of a characteristic, they’ll iterate extra slowly or they’ll choose to construct a so-called backend-driven UI. A backend-driven UI is a consumer interface that’s drawn by fetching details about the UI from a server, parsing the knowledge, and putting acceptable UI elements on display primarily based on the retrieved information.

One of the crucial essential elements in an app that implements in-app purchases is the paywall. You wish to ensure that your paywall is introduced on the proper time, and that it presents the very best provide to your consumer in one of the best ways. Normally, you’ll wish to iterate in your paywall and experiment with completely different configurations to resolve which paywall converts finest to your app.

On this submit, we’ll discover RevenueCat’s paywall characteristic to see how we will leverage this characteristic to construct a backend-driven, native paywall to your apps.

This submit is a sponsored submit. Its goal is to offer an sincere and truthful view on RevenueCat. To ensure that this submit is effective to my readers, all opinions expressed on this submit are my very own.

Understanding what backend-driven is

In the event you suppose {that a} backend-driven UI sounds extremely sophisticated, that’s as a result of it may be very advanced certainly. The only model of a backend-driven UI is a UI that hundreds JSON, parses that JSON into mannequin objects, after which your views render the parsed fashions right into a SwiftUI checklist view.

On this instance, the backend didn’t resolve how your display seems to be, but it surely did inform your app about what needs to be introduced to the consumer. In fact, it is a quite simple instance of a backend-driven UI and it’s often not what individuals imply once they discuss being backend-driven but it surely does show the fundamentals of being backend-driven with out being overly advanced.

After we apply the concept of being backend-driven to RevenueCat paywalls, what we’re speaking about is the power for a backend to inform your app precisely which in-app purchases, metadata and UI components needs to be proven to your consumer.

Let’s get began by how one can arrange the RevenueCat facet of issues by configuring a paywall and its contents. After that, we’ll see how we will leverage the RevenueCat paywall in an app to point out our paywall with backend-driven elements.

Establishing RevenueCat for backend pushed paywalls

In the event you’ve labored with RevenueCat earlier than, you’ll know that RevenueCat fashions your in-app purchases by entitlements, merchandise and choices. Briefly, right here’s what every of those configurations are for:

  • Entitlement An entitlement is what “marks” your consumer as accessing a number of options in your app. Having “professional entry” to an app is an instance of an entitlement.
  • Product These map to your in app purchases in App Retailer Join. For instance, you’ll be able to have a month-to-month, yearly and lifelong subscription enabled to your app. These are three separate merchandise in App Retailer Join however all three can unlock the identical entitlement in RevenueCat.
  • Choices An providing in RevenueCat is a set of merchandise that you just group collectively as a paywall. This lets you experiment with completely different merchandise being provided to your consumer (for instance, you’ll be able to have an providing that exhibits your month-to-month / yearly subscriptions, one which solely exhibits your lifetime subscription, and one which exhibits all of your merchandise). You’ll be able to programmatically resolve which providing is introduced to a consumer. You’ll be able to even arrange experiments to current completely different affords to your customers as a method of A/B testing your pricing technique.

With a view to implement a backend pushed paywall, you’ll need to have created your entitlements and merchandise. In the event you’re simply getting began with RevenueCat, they’ve nice documentation obtainable that will help you get arrange rapidly.

The trick to implementing a backend-driven paywall is in the way you arrange your provide.

RevenueCat permits you to affiliate JSON metadata together with your providing. You’re free to incorporate as a lot metadata as you’d like which implies that you may present a great deal of paywall associated info for a particular provide as metadata.

Screenshot 2024-03-26 at 11.55.38.png

For instance, whenever you’re presenting your lifetime subscription solely providing, you may want your app to focus on the options your consumer unlocks together with some constructive consumer critiques. If you’re presenting a consumer with the choice to decide on a month-to-month vs. yearly subscription, you can choose to current the consumer with some advantages of selecting yearly as an alternative of month-to-month.

You would possibly wish to change issues up after you’ve tried an method for some time.

All of that is attainable by associating the best metadata to your providing. Within the subsequent part, I’ll present you what this seems to be like from an app standpoint. For now, we’ll give attention to the considerably extra summary JSON facet of issues.

Slightly than exhibiting you all the pieces that’s attainable with this JSON, I’d prefer to give attention to presenting one thing comparatively easy. If you wish to see a extra elaborate instance of what may be completed, try this speak from RevenueCat’s Charlie Chapman the place he demoes backend-driven paywalls in addition to the corresponding demo app code.

For the needs of this weblog submit, right here’s the JSON I’ll be working with:

{
  "default_selection": "$rc_annual",
  "header": {
    "description": "Get the professional model of TinySteps and revel in limitless actions in addition to a handy sharing characteristic.",
    "title": "Go professional right now!"
  }
}

All we’re doing right here is organising a easy header object in addition to configuring a default chosen bundle. This may enable us to experiment with pre-selecting a subscription to see whether or not that impacts a consumer’s selection between yearly and month-to-month subscriptions.

Right here’s what that find yourself trying like in RevenueCat’s UI.

Screenshot 2024-03-26 at 12.09.53.png

Now that we’ve arrange our providing, let’s check out how we will leverage this in our app.

Presenting the paywall in your app

When you’ve included the RevenueCat SDK in your app and also you’ve configured it together with your api key, you can begin implementing your paywall. For this submit, we’ll implement a quite simple paywall that shows our header, lists all completely different subscription varieties that we now have obtainable, and we pre-select the subscription that we’ve configured in our JSON metadata.

To get began, we should always write out the mannequin that we intend to decode from our JSON Metadata. On this case, we’re working with pretty easy information so our mannequin may be easy too:

struct PaywallInfo: Decodable {
  let defaultSelection: String
  let header: Header
}

extension PaywallInfo {
  struct Header: Decodable {
    let description: String
    let title: String
  }
}

To load PaywallInfo from our metadata, we will fetch our providing from RevenueCat, extract the metadata, after which decode that metadata into our mannequin object.

Right here’s what that would seem like:

enum PaywallLoader {
  static func getPayWallInfo() async -> (PaywallInfo, [Package])? {
    do {
      guard let providing = attempt await Purchases.shared.choices().present else {
        return nil
      }

      let information = attempt JSONSerialization.information(withJSONObject: providing.metadata)
      let decoder = JSONDecoder()
      decoder.keyDecodingStrategy = .convertFromSnakeCase
      let paywallInfo = attempt decoder.decode(PaywallInfo.self, from: information)

      let packages = providing.availablePackages

      return (paywallInfo, packages)
    } catch {
      print("Error: (error)")
      return nil
    }
  }
}

Within the snippet above, you would possibly discover the next strains and marvel what they do:

let information = attempt JSONSerialization.information(withJSONObject: providing.metadata)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let paywallInfo = attempt decoder.decode(PaywallInfo.self, from: information)

The metadata JSON that we get on our providing is of kind [String: Any]. We all know that this information originated as JSON from the RevenueCat admin panel however we would like to have the ability to remodel the [String: Any] dictionary into our mannequin object. To do that we convert the dictionary to Information, and from Information into our mannequin. It’s a bit of tedious but it surely works.

As soon as we’ve retrieved our information, we will use it to populate our view.

The next exhibits a particularly bare-bones instance of utilizing our PaywallLoader in a view:

struct PaywallMainView: View {
  @State var paywallData: (PaywallInfo, [Package])?
  @State var selectedPackage: Package deal?

  var physique: some View {
    if let paywallData {
      VStack {
        Textual content(paywallData.0.header.title)
          .font(.title)

        Textual content(paywallData.0.header.description)
          .font(.title)

        ForEach(paywallData.1) { bundle in
          if bundle.identifier == selectedPackage?.identifier {
            Button(bundle.storeProduct.localizedTitle, motion: {
              selectedPackage = bundle
            })
            .background(Coloration.grey)
          } else {
            Button(bundle.storeProduct.localizedTitle, motion: {
              selectedPackage = bundle
            })
          }
        }
      }
    } else {
      ProgressView()
        .process {
          paywallData = await PaywallLoader.getPayWallInfo()
          selectedPackage = paywallData?.1.first(the place: { bundle in
            return bundle.identifier == paywallData?.0.defaultSelection
          })
        }
    }
  }
}

This code is solely supplied as a reference to point out you what’s subsequent after decoding your mannequin information. It’s not meant to look fairly, neither is it meant to point out you essentially the most stunning paywall. The important thing lesson right here is that you may leverage the JSON metadata on a RevenueCat providing to construct a paywall that makes use of backend-driven UI, permitting you to experiment with completely different texts, configuration and extra.

In Abstract

There’s no restrict to how versatile you may get with a backend-driven UI apart from your creativeness. On this submit, I’ve proven you a really primary backend-driven UI that might enable me to vary a default choice for my paywall and to experiment with completely different texts on my paywall.

You’ve seen how one can configure an providing in your RevenueCat console with any JSON you’d like, permitting you to experiment to your coronary heart’s content material. You’ve additionally seen how one can write code that fetches an providing and extract the related info from the JSON metadata.

Once more, there’s just about no restrict to what you are able to do right here. You’ll be able to present as a lot JSON information as you’d prefer to construct advanced, dynamic, and customizable paywalls that may be up to date on the fly. No App Assessment wanted.

I’m a giant fan of RevenueCat’s implementation of JSON metadata. Having the ability to increase the obtainable info like it is a enormous profit to experimentation and testing to seek out out the very best paywall implementation to your app.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments