> They still don't support upgrades/upgrade pricing.
What would this mean, exactly?
You can sell people a demo→full-version permanent unlock as a one-time purchase, same as you can sell DLC in a game.
And you can also have subscription tiers, where you get more features out of the higher tiers of subscriptions.
And you can, in theory, freely mix these — e.g. charging someone a subscription for the base version, and then charging them a one-time fee to unlock a specific feature.
If you want, you could even charge for app features as consumables (just like F2P games do) — where you pay to have a block of credits that you use up, or you pay for one month and then have to buy it again when it runs out.
The model is the "old school" model for software sales.
The first version you sell to a user at full price and offer a discount for upgrading (something like 40% off). It lets the customer pick when they feel the value prop is worth the cost and lets you offer a loyalty incentive to the user.
Right now the choice is "keep paying for it to keep working" or "fully price for every upgrade".
I don’t exactly remember how it went but ~5 years ago Goodnotes 5 came out and they offered a “bundle” of Goodnotes 4 and 5 together at the same price of Goodnotes 5. Maybe owners of version 4 had some kind of discount on the bundle because they already owned half of it?
Bundles can be used for upgrade pricing, you put the new version up for full price (ie. $20) and and a bundle with the new and old version (ie $30, for a 50% discount on it) for those who own the old version. When you buy a bundle you don't pay for the one you own.
Are there any examples of apps that do that? As a consumer, I haven't ever heard of an app that offers this (e.g. goodnotes, LiquidText, MarginNote, Audulus and Things have new major releases and don't seem to do this)
Couple of the old school macOS dev houses tried this once this hack became visible and little birdies said the hack WAI. (ex. OmniGroup)
Since then, people have backed off.
If you're going to this much work to help users workaround Apple nonsense, you really care about helping them save money, and the support + refund costs of people accidentally buying the bundle with the old version they don't need is > just building out your own server-side system, versus a combinatorial explosion of bundles in the App Store that creates a confusing minefield for users.
By jumping through hoops, tying unrelated tools together, confusing users, and reaping an extra $10 you didn't want to take + support costs thereof, yes, it is possible. It is not what we expected or asked for when we started asking for this in 2007 (we = iOS devs).
There are several vendors who do this, for instance 1Password and the Omni Group both do. You have an in-app purchase option that is unlocked by a previous receipt. The challenge is that Apple does not provide tools to help or guidance. They do indeed think e.g. requiring users to buy an upgrade to keep the app working on a new annual iOS version or macOS version is a bad model for users.
Panic even had an upgrade for MAS users when they released their new version of the now defunct Coda outside the MAS (for sandboxing reasons).
Free upgrades are problematic themselves: once you've saturated your market (a good place to be, right?) you no longer have income to provide upgrades.
There's nothing actually stopping you from doing this — it requires two things:
1. either a third-party licensing server (and thus some SSO auth system — but just require Apple's own SSO for it and it'll still be a clean-ish workflow) to share/sync the transaction status from one app to the other; or a local Group Container plus logic in each app to write the transaction statuses fetched for the given app into the group container for the other app to read
2. never charging for the app as a whole, but instead breaking your app's pricing down into a set of IAP-purchased feature entitlements (whether charged for individually, or as a bundle, the important part is that each entitlement has its own price.) Then, making the new version just a superset of the features of the old version — and so, when you're buying the old version, you're buying features A+B+C; and then when you're buying the new version (with the app being able to see whether or not you've bought the old version), new customers are buying A+B+C+D+E, while existing customers are buying D+E.
---
Note that there's an even easier way to do this (and I think this is the way Apple would prefer you do this): don't release V2 as a separate app from V1.
Instead, have V1 auto-update to a v2.0.0 release — which converts the V1 app into a launcher with an "edition" (major version) selector. Either compile in both the V1 and V2 codebase into this app, or better yet (for download/on-disk size), package separate V1 and V2 "engines" as executable DLC packages, submitted to Apple for review along with the app, downloaded on-demand when the app needs to run them.
With this approach, the app would either start up the first time still within V1, and allow/offer people the option of "seamlessly upgrading" the app to V2; or the app would start up with an "edition launcher" UI that allows people a choice. (And either way, you could offer the ability at any time to freely switch between V2 and V1, re-launching the app with the other engine enabled. Like dual-booting Operating Systems, but at the app level.)
Here, you could charge for the V2 "upgrade" ahead-of-time, before allowing the user to switch over to the V2 engine; or you could allow the user to switch between V1-fully-licensed and V2-demo modes (or even between V1-demo and V2-demo modes), where purchasing for each edition is separately available within that edition's UX.
The expectation here is that all the user's existing feature entitlements would keep working as long as they continue to use the V1 engine — as you said, the V1 engine was a one-time purchase, and so even with this edition-launcher abstraction introduced in v2.0.0 of the app, V1 itself should still keep working for them forever.
The benefit of doing this multi-editioned-shared-app approach, together with IAP feature entitlements, is that V2 can inherit some of the V1 entitlements, and then simply charge for the V2-novel entitlements. So V2 gets discounted for V1 purchasers inherently, by the fact that by buying V1, they've already bought half of the components of the V2 purchase-bundle.
So whereas authors used to ship a new version, and let people upgrade to that version at a discount, the author now assumes the burden with each new release of maintaining and testing V1 (that’s with all the feature flags turned off) as well as every feature flag between V1 and Vcurrent turned on. One at a time. Sounds like insanity to me.
That would be a choice, not a requirement. It's literally a flag. You can do whatever tf you want with it. It would be trivial to have "V1 full app unlock" feature be the same as "V2 full app unlock" feature.
@jayd16 - it’s been a few years since I read the Apple Developer Agreement but at that time downloading code and executing it within your app was forbidden by the agreement. A sensible security safeguard IMO.
AFAIK, even the iSH developers were never given a proper explanation. iSH was actually removed a few years back[0] and then reinstated with an apology but no policy changes or clarifications.
This was before the change to allow Delta on the App Store, too.
There's a lot of nuance here. Some of it is ours, some of it is on Apple's side. Before I get into it I will say that most of what I say about Apple's side is largely not a position they will clarify or take publicly, and some of it is our interpretation. When iSH was removed from the store we did push them to clarify this in the App Store Review Guidelines but they chose to not do so.
When you run an App Store that involves human review the big problem you have is apps that mask their behavior during review and then end up breaking the rules later. My understanding is that the "don't download code" policy is intended to prevent this, at least in spirit. I think, at least at the highest level of the company, the intent is to keep to somewhere near this at least for submissions made in good faith and not prone to opening them up to a slippery slope. There are distinctions here, though, and policy enforcement is also complicated.
My (and iSH's) position is that "code" should be interpreted very broadly, including native code (which the platform blocks from loading anyways) but also things like embedded webviews updated server-side or those "code-push"/"run JavaScript in an interpreter in your app" things. And going even beyond that, I feel that to provide a full experience for the review team when you ship a feature flag you really ought to list all the behaviors that the app can possibly have, and let the review team test that if they want.
From this perspective you will note that code isn't even really the interesting part here, it's the behavior changing that matters. So this leads naturally what we have described as "scripting apps", which download code but do not change their behavior. Their entire point is to download code. Like, App Store is an app store, regardless of whether you download TikTok or Google Maps from it. iSH is a a Linux environment. Nothing you will do in the app will change that. And notably we have zero ability to change that ourselves, short of submitting a new app. It's not like we can just add Windows emulation as a downloadable JavaScript package without going through review. From our discussions with leadership, I think they agree with us on it, but are not willing to commit to it publicly, because then people will take creative bad-faith interpretations of it to argue what a feature of the app versus something a user does in the app is, or something like that. Or they just want to hold all the cards and reserve the right to take this away. Either way I strongly disagree with them doing this, but for now iSH remains on the store.
You will note that the changes we make (see our blog post about repositories: https://ish.app/blog/default-repository-update) continue to support that position. Again, I cannot say for sure whether this is the interpretation Apple uses, or if they even have a consistent position. It's just an attempt on our side to show good faith. As a final note our experience has been that the higher you go the more consistent and reasonable review becomes, but the front-line reviewers often take stupid, unreasonable positions like you'd see in a Hacker News comment (it says code therefore your app for coding is bad). But again, this is just our experience; we have no idea if Phill will hit his head tomorrow and decide to pull iSH tomorrow because he thinks Linux is the child of the devil.
>As a final note our experience has been that the higher you go the more consistent and reasonable review becomes, but the front-line reviewers often take stupid, unreasonable positions like you'd see in a Hacker News comment
A sadly universal experience. Especially when the not-so-secret is that that frontline is often contracted or outsourced. They do not understand (by design) the subtleties of submission of creative content. They are simply cheap help to do the bare minimum to remove liability, and if a few false negatives happen during that time, oh well. thousands of other apps in the sea.
So like everything else, if you havev the money, clout, or simply sheer persistence (which shouldn't be necessary) then you can force yourself to someone who can actually help. But few will get there, even with persistance.
What you've said largely tracks with my interpretation of Apple's actions here.
> I feel that to provide a full experience for the review team when you ship a feature flag you really ought to list all the behaviors that the app can possibly have, and let the review team test that if they want.
After Epic added direct purchase gated behind a feature flag to Fortnite, I'm genuinely surprised Apple didn't start requiring full control over and documentation of all downloadable configuration files as part of App Review.
While being vaguely on the side of review being not very useful I would agree with Apple doing that if only to make their position more consistent, even though I am sure every developer would riot if this was the case. (Although I vaguely remember someone saying we provided feature flags to Apple when we submitted builds at Twitter. But do take it with a grain of salt, since I wasn't on the release team and my view of them is vaguely positive in that I think they generally didn't try to use tricks to get through review.)
Odds are their "front line" reviewers are not highly technical, so Apple wouldn't want to commit to that. They are more than large enough to afford a few inefficiencies and pick fights the few times something like iSH "slip in".
Lot of stuff can skirt by until it doesn't. That's how stuff like Beeper suddenly explodes into a kerfluffle in a matter of days over some dang blue bubbles.
Re: feature entitlements shared through a shared SSO auth backend and/or Group Container — yes, apps do this. Mostly this is in app "suites" where you can IAP a feature entitlement in one app in the suite, and the entitlement should then become available to the other apps in the suite. (I think the Omni Group apps do it? Correct me if I'm wrong.)
Re: multi-edition shared apps — I'm not sure if this has been done with the App Store in particular, but it's just a combination of things App Store apps can do (basically, moving code out into dylibs, and then marking those dylibs as On-Demand Resources.) I know that this is a common approach to supporting netplay (and especially replay of historical netplay) in competitive-eSport multiplayer game titles on Steam et al, where players need to be on the same exact version of the game engine + netcode to sync (and so those engine libs are downloaded on-demand before the match begins); and where you need an exact ABI version of the game engine to replay a netplay recording (and so that engine lib is downloaded on-demand when you go to replay the recording.)
ETA: looking more into this, I'm finding conflicting reports on whether executable-code On-Demand Resources are currently allowed on the iOS App Store: it looks like the Apple docs say no, and yet some apps (from not-bigcorp devs!) are doing it anyway and getting away with it (and have for many review cycles.) Very confusing. Maybe those devs are part of an alpha-test rollout for executable-ODR?
What would this mean, exactly?
You can sell people a demo→full-version permanent unlock as a one-time purchase, same as you can sell DLC in a game.
And you can also have subscription tiers, where you get more features out of the higher tiers of subscriptions.
And you can, in theory, freely mix these — e.g. charging someone a subscription for the base version, and then charging them a one-time fee to unlock a specific feature.
If you want, you could even charge for app features as consumables (just like F2P games do) — where you pay to have a block of credits that you use up, or you pay for one month and then have to buy it again when it runs out.
What's the missing revenue model here?