All posts
3 min readBy Anggaarchitecture / RevenueCat / deep linking / mobile

A cross-app discount with no backend

Giving players 50% off in a sibling app when they already paid in one, using a deep-link handshake instead of sign-in, accounts, or a server.

I wanted loyalty to span the family: if you bought Pro or removed ads in one TTS app, you should get 50% off in the others. The obvious way to do that is a shared user identity. I did not want to build one.

Why not sign-in

A shared discount needs to know "is this the same person across apps". The textbook answer is sign-in: add Google or Apple login, give RevenueCat a stable user id, check entitlements across apps. That is a real third-party integration, a real auth UI, and a real support surface. For a discount, not free product, it felt like too much.

Play Games Services does not save you here either. Its player ids are game-scoped, so the same person gets a different id in each of your games. No shared identity without a backend to exchange tokens, which is the thing I was avoiding.

The insight: the apps can talk to each other

All four apps are mine, installed on the same device, signed with the same key. They do not need a server to coordinate. They can deep-link to each other.

So the flow is:

  1. In an app where you own Pro or remove-ads, Settings shows a "Claim 50% in TTS Gen Z" button for each sibling.
  2. Tapping it opens the sibling via its deep-link scheme with a shared token: ttsgenz://loyalty?token=.... If the sibling is not installed, its Play listing opens instead so you can get it.
  3. The sibling receives the link on a /loyalty route, verifies the token, and persists an eligibility flag.
  4. From then on, the sibling's paywall sells from a discounted RevenueCat offering (loyalty50) instead of the default one, with the original prices struck through.

No accounts. No backend. No third-party identity. Just four apps that trust each other because they all came from me.

The store side

RevenueCat does not invent discounts; the store does. So:

  • In Play Console, each subscription base plan gets a 50% offer with developer-determined eligibility. That phrase is the key: Google cannot know "owns Pro in a sibling app", only my app knows, so the offer is one only the app can present.
  • The one-time remove-ads product gets a half-price sibling product (one-time buys cannot carry offers).
  • In RevenueCat, a loyalty50 offering bundles the discounted packages. It is not marked current, so it is invisible to everyone except an eligible install that requests it by id.

One subtlety that would have silently charged full price: RevenueCat does not auto-apply developer-determined offers. You have to purchase the specific subscription option (the one whose id matches your offer), not just the package. Miss that and the discounted offering still rings up at base price.

The honest tradeoff

The token ships inside the app bundle. A determined person could decompile an APK and forge eligibility. For a discount that only ever yields 50% off, never a free product, that is an acceptable trade for zero backend. Eligibility is also device-local, so on a new phone you tap the claim button again. Both are fine for what this is.

The lesson

Before you reach for the heavyweight solution (auth, identity, a server), ask what you actually need to know and who already knows it. I needed "did this person pay in a sibling app", and the sibling app already knew. The whole feature collapsed into a deep link and a flag.

Next: getting all of this past Google and onto the store.