Mobile Store Integration
Connect a mobile game to the store platforms it ships on: purchase flows, receipt validation, ad monetization, and social/achievement services on iOS (App Store / StoreKit / Game Center) and Android (Google Play / Billing / Play Games Services).
This skill owns the store-platform contract itself — product configuration, the validation server, ad mediation strategy, and social services — which applies across Unity, Unreal, native, and Godot alike. The mobile-development skill owns the Godot engine-side export and runtime (Billing 5 plugin, StoreKit bridge, AndroidRuntime).
When to Use
- In-App Purchases: configuring consumables, non-consumables, auto-renewing subscriptions; the buy → validate → grant flow.
- Receipt validation: verifying purchases server-side against Apple/Google to defeat client tampering.
- Ad monetization: integrating banner/interstitial/rewarded ads via a mediation layer (AdMob, Unity LevelPlay, AppLovin MAX).
- Social services: Game Center / Play Games Services authentication, achievements, leaderboards, and cloud saved games.
- Store submission: App Store Connect / Play Console product setup, metadata, review-readiness.
Do Not Use
| If the task is… |
Use instead |
| Godot export, signing, AAB/IPA build, Godot billing plugin wiring |
mobile-development |
| Steam achievements/leaderboards/Workshop/Cloud on PC |
steamworks-sdk |
| Web/server credit-card payments, Stripe subscriptions |
stripe-integration |
| Console store/online cert (Switch/PS/Xbox) |
console-porting-certification |
Prerequisites
- A paid Apple Developer Program membership (for App Store Connect / StoreKit 2 / Game Center).
- A Google Play Developer account (one-time $25 registration fee) with a configured app in the Play Console.
- A backend server you control for receipt validation — never grant entitlement on the client alone.
- For Google Play Developer API: a Google Cloud service account with the
Android Publisher role and a downloaded JSON key.
- For Apple App Store Server API: an issuer ID, key ID, and downloaded
.p8 key from App Store Connect → Users and Access → Keys.
- For ad mediation: accounts on each ad network (AdMob, Unity LevelPlay, AppLovin MAX) plus the mediation SDK integrated into your build.
- Store products (IAPs, achievements, leaderboards) defined in App Store Connect / Play Console before the client API references their IDs.
Procedure
1. Purchase Flow (the only correct shape)
client: request products ──► store SDK returns localized price
client: user taps buy ──► store SDK runs the payment sheet
store: returns a signed receipt / purchase token
│
▼ send token to YOUR server (never grant on the client alone)
server: verify with Apple/Google API ──► grant entitlement, record txn
│
▼
client: finish/acknowledge the transaction ◄── only after server confirms
Cardinal rule: the client never decides a purchase is valid. A jailbroken/rooted device can fake any client-side "success." Entitlement is granted by your server after it verifies the receipt with the platform.
2. Configure In-App Purchase Products
| Type |
iOS (StoreKit) |
Android (Play Billing) |
Must be |
| Consumable (gems, lives) |
Consumable |
INAPP, consumed after grant |
Consumed so it can be re-bought |
| Non-consumable (remove ads, unlock) |
Non-Consumable |
INAPP, acknowledged |
Restorable; never consumed |
| Auto-renewing subscription |
Auto-Renewable |
SUBS |
Server-tracked renewal state |
- Define products in the store console first — App Store Connect → In-App Purchases, or Play Console → Monetize → Products. The client API only references IDs that already exist there.
- Consumables must be consumed (Android) / finished (iOS) after the server grants them — otherwise the user can't buy again.
- Non-consumables & subscriptions must support Restore Purchases (Apple requires a visible restore path). Re-query entitlements on fresh installs / new devices.
- Acknowledge within the window: Google Play auto-refunds any purchase not acknowledged within 3 days. Acknowledge (or consume) only after your server grants.
- Display store-returned localized prices — never hardcoded strings. Currencies, tiers, and taxes vary by region.
3. Implement Server-Side Receipt Validation
Apple (StoreKit 2)
- Use StoreKit 2 only — StoreKit 1 and
/verifyReceipt are deprecated.
- On the server, verify the JWS signature against Apple's root CA — don't just decode the payload.
- Check
bundleId, environment (sandbox vs production), and transactionId in the verified payload.
- Use the App Store Server API + App Store Server Notifications v2 as the source of truth for subscription state, refunds, and revocations.
- Persist every
transactionId to detect replays.
Google (Play Billing)
- Ship the current Play Billing Library major — Play enforces a minimum version yearly and blocks updates on stale majors.
- Verify the purchase token with the Google Play Developer API:
purchases.products.get for one-time purchases
purchases.subscriptionsv2.get for subscriptions
- Use a service account with the
Android Publisher role; authenticate with the downloaded JSON key.
- Acknowledge/consume server-side via the API after granting.
- Subscribe to Real-time Developer Notifications (RTDN) over Pub/Sub for renewals, cancels, refunds.
Both platforms
- Persist every transaction id / purchase token to detect replays — the same token submitted twice must not double-grant.
- Validate the bundle id / package name and product id in the receipt match your app — don't trust the client's claim of what was bought.
4. Integrate Ad Mediation
Game ── rewarded ad request ──► Mediation SDK (AdMob / LevelPlay / MAX)
│ real-time bidding across networks
▼ highest-paying fill wins
onUserEarnedReward ──► grant reward ONCE
- Use a mediation layer, not a single ad network — it fills inventory and raises eCPM via real-time bidding (waterfalls are legacy; prefer bidding-first setups). Don't hand-integrate five SDKs separately. LevelPlay is Unity's mediation (formerly ironSource).
- Rewarded ads: grant the reward only in the
onUserEarnedReward / completion callback, exactly once. Never grant on "ad opened" or on the close callback.
- Preload interstitials/rewarded ahead of the moment you show them; a cold request at the show point fails to fill and feels broken.
- Respect ATT (App Tracking Transparency) on iOS and consent (UMP/GDPR/CMP) before initializing ad SDKs, or you violate policy and lose fill.
- Attribution is privacy-preserving now: AdAttributionKit (successor to SKAdNetwork) on iOS, Privacy Sandbox Attribution Reporting alongside GAID on Android. Don't build UA measurement on device-ID fingerprinting.
- Don't interrupt active gameplay with interstitials; show at natural breaks (level end), and cap frequency.
5. Wire Social Services (Game Center / Play Games)
Use Play Games Services v2 on Android — v1 sign-in is shut down; v2 does automatic sign-in at launch with no consent screen for basic auth.
| Capability |
Game Center (iOS) |
Play Games Services v2 (Android) |
| Sign-in |
GKLocalPlayer.authenticate |
GamesSignInClient / one-tap |
| Achievements |
GKAchievement (percent → 100 = unlocked) |
incremental or standard, defined in console |
| Leaderboards |
GKLeaderboard submit/load |
LeaderboardsClient submit/load |
| Cloud saves |
iCloud / GKSavedGame |
Snapshots API (handle conflict resolution) |
- Define achievements/leaderboards in App Store Connect / Play Console first; the API only references IDs that already exist there.
- Authenticate early and silently; degrade gracefully if the user declines or is offline — never block game entry on a social sign-in.
- For cloud saves, you must implement conflict resolution (two devices, divergent saves). The Snapshots/GKSavedGame API surfaces conflicts; don't blind-overwrite.
6. Prepare for Store Submission
- iOS: app must have at least one IAP submitted with the app's first review if monetization is core; provide a sandbox tester account flow; privacy nutrition labels and ATT usage string are mandatory.
- Android: upload a signed AAB; create products in Play Console (they're inactive until the app is published to a track); use license testers for unpaid sandbox purchases.
- Stay on the platform treadmill: Play raises the required target API level every August; Apple raises the minimum Xcode/SDK every spring. A store-compliant build today is rejectable next year without touching your code.
- Alternative billing / external purchase links (EU DMA, Google user-choice billing, US anti-steering entitlements) are region- and program-gated compliance work — don't treat them as the default flow, and keep the standard store flow working everywhere.
- Test purchases in sandbox/test tracks before production — real charges in review get the build rejected.
Pitfalls
- Client-side entitlement: granting the item because the client SDK said "purchased." Always validate on a server you control.
- Not consuming consumables: user buys 100 gems once and can never buy again. Consume after grant.
- No restore path: Apple rejects apps with non-consumables/subscriptions that lack Restore Purchases.
- Ignoring the Google acknowledge window: unacknowledged purchases auto-refund in 3 days — the user is charged then refunded and you look broken.
- Granting rewarded reward on the wrong callback: granting on close instead of
onUserEarnedReward lets users skip the ad and still get paid.
- Initializing ad SDKs before consent/ATT: policy violation, lost fill, possible removal.
- Trusting receipt fields blindly: always re-verify bundle/package id and product id against your catalog; check for replayed transaction ids.
- Hardcoding prices: always show the store-returned localized price, never a string you typed — currencies, tiers, and taxes vary by region.
- Blocking launch on social sign-in: make Game Center/Play Games optional and async.
- Using Play Games Services v1: v1 sign-in is shut down. Use v2 only.
- Using StoreKit 1 /
/verifyReceipt: deprecated. Build on StoreKit 2 and JWS signature verification.
- Stale Play Billing Library major: Play blocks updates on outdated majors. Track the yearly minimum bump.
Verification
Related Skills
mobile-development — Godot engine-side export, signing, and the in-engine billing/ads plugins this contract sits behind.
steamworks-sdk — The PC/Steam equivalent for ownership, achievements, leaderboards, and Cloud.
stripe-integration — Web/server payments when selling outside the mobile stores.
console-porting-certification — Console store and online service equivalents when porting beyond mobile.
References
- Apple StoreKit 2, App Store Server API, and App Store Server Notifications v2 documentation.
- Google Play Billing Library and Google Play Developer API (purchases & subscriptions) documentation.
- Google Mobile Ads (AdMob) mediation, Unity LevelPlay, and AppLovin MAX integration guides.
- Apple AdAttributionKit and Android Privacy Sandbox Attribution Reporting documentation.
- Apple GameKit (Game Center) and Google Play Games Services v2 documentation.
1---2name: game-mobile-store-integration3description: Wires mobile games to App Store and Google Play: StoreKit 2 / Play Billing with server-side receipt validation, AdMob/LevelPlay/MAX mediation, and Game Center / Play Games Services v2. Use when the user mentions IAP, receipt validation, App Store Connect, Play Console, rewarded ads, GameKit, or Play Games. Not for Godot export/signing (mobile-development), Steam, Stripe, or console stores. Never grant entitlement from the client SDK alone.4---5
6# Mobile Store Integration
7
8Connect a mobile game to the store platforms it ships on: purchase flows, receipt validation, ad monetization, and social/achievement services on iOS (App Store / StoreKit / Game Center) and Android (Google Play / Billing / Play Games Services).
9
10This skill owns the **store-platform contract** itself — product configuration, the validation server, ad mediation strategy, and social services — which applies across Unity, Unreal, native, and Godot alike. The `mobile-development` skill owns the **Godot engine-side** export and runtime (Billing 5 plugin, StoreKit bridge, AndroidRuntime).
11
12## When to Use
13
14- **In-App Purchases**: configuring consumables, non-consumables, auto-renewing subscriptions; the buy → validate → grant flow.
15- **Receipt validation**: verifying purchases **server-side** against Apple/Google to defeat client tampering.
16- **Ad monetization**: integrating banner/interstitial/**rewarded** ads via a mediation layer (AdMob, Unity LevelPlay, AppLovin MAX).
17- **Social services**: Game Center / Play Games Services authentication, achievements, leaderboards, and cloud saved games.
18- **Store submission**: App Store Connect / Play Console product setup, metadata, review-readiness.
19
20### Do Not Use
21
22| If the task is… | Use instead |
23|---|---|
24| Godot export, signing, AAB/IPA build, Godot billing plugin wiring | `mobile-development` |
25| Steam achievements/leaderboards/Workshop/Cloud on PC | `steamworks-sdk` |
26| Web/server credit-card payments, Stripe subscriptions | `stripe-integration` |
27| Console store/online cert (Switch/PS/Xbox) | `console-porting-certification` |
28
29## Prerequisites
30
31- A paid Apple Developer Program membership (for App Store Connect / StoreKit 2 / Game Center).
32- A Google Play Developer account (one-time $25 registration fee) with a configured app in the Play Console.
33- A backend server you control for receipt validation — never grant entitlement on the client alone.
34- For Google Play Developer API: a Google Cloud service account with the `Android Publisher` role and a downloaded JSON key.
35- For Apple App Store Server API: an issuer ID, key ID, and downloaded `.p8` key from App Store Connect → Users and Access → Keys.
36- For ad mediation: accounts on each ad network (AdMob, Unity LevelPlay, AppLovin MAX) plus the mediation SDK integrated into your build.
37- Store products (IAPs, achievements, leaderboards) defined in App Store Connect / Play Console **before** the client API references their IDs.
38
39## Procedure
40
41### 1. Purchase Flow (the only correct shape)
42
43```
44client: request products ──► store SDK returns localized price
45client: user taps buy ──► store SDK runs the payment sheet
46store: returns a signed receipt / purchase token
47 │
48 ▼ send token to YOUR server (never grant on the client alone)
49server: verify with Apple/Google API ──► grant entitlement, record txn
50 │
51 ▼
52client: finish/acknowledge the transaction ◄── only after server confirms
53```
54
55**Cardinal rule**: the client never decides a purchase is valid. A jailbroken/rooted device can fake any client-side "success." Entitlement is granted by your server after it verifies the receipt with the platform.
56
57### 2. Configure In-App Purchase Products
58
59| Type | iOS (StoreKit) | Android (Play Billing) | Must be |
60|---|---|---|---|
61| Consumable (gems, lives) | Consumable | INAPP, consumed after grant | Consumed so it can be re-bought |
62| Non-consumable (remove ads, unlock) | Non-Consumable | INAPP, acknowledged | Restorable; never consumed |
63| Auto-renewing subscription | Auto-Renewable | SUBS | Server-tracked renewal state |
64
651. **Define products in the store console first** — App Store Connect → In-App Purchases, or Play Console → Monetize → Products. The client API only references IDs that already exist there.
662. **Consumables** must be **consumed** (Android) / finished (iOS) after the server grants them — otherwise the user can't buy again.
673. **Non-consumables & subscriptions** must support **Restore Purchases** (Apple requires a visible restore path). Re-query entitlements on fresh installs / new devices.
684. **Acknowledge within the window**: Google Play auto-refunds any purchase not acknowledged within 3 days. Acknowledge (or consume) only after your server grants.
695. **Display store-returned localized prices** — never hardcoded strings. Currencies, tiers, and taxes vary by region.
70
71### 3. Implement Server-Side Receipt Validation
72
73#### Apple (StoreKit 2)
74
751. Use **StoreKit 2** only — StoreKit 1 and `/verifyReceipt` are deprecated.
762. On the server, verify the **JWS signature against Apple's root CA** — don't just decode the payload.
773. Check `bundleId`, `environment` (sandbox vs production), and `transactionId` in the verified payload.
784. Use the **App Store Server API** + **App Store Server Notifications v2** as the source of truth for subscription state, refunds, and revocations.
795. Persist every `transactionId` to detect replays.
80
81#### Google (Play Billing)
82
831. Ship the current **Play Billing Library major** — Play enforces a minimum version yearly and blocks updates on stale majors.
842. Verify the purchase token with the **Google Play Developer API**:
85 - `purchases.products.get` for one-time purchases
86 - `purchases.subscriptionsv2.get` for subscriptions
873. Use a service account with the `Android Publisher` role; authenticate with the downloaded JSON key.
884. Acknowledge/consume server-side via the API after granting.
895. Subscribe to **Real-time Developer Notifications (RTDN)** over Pub/Sub for renewals, cancels, refunds.
90
91#### Both platforms
92
93- Persist every transaction id / purchase token to **detect replays** — the same token submitted twice must not double-grant.
94- Validate the **bundle id / package name** and product id in the receipt match your app — don't trust the client's claim of what was bought.
95
96### 4. Integrate Ad Mediation
97
98```
99Game ── rewarded ad request ──► Mediation SDK (AdMob / LevelPlay / MAX)
100 │ real-time bidding across networks
101 ▼ highest-paying fill wins
102 onUserEarnedReward ──► grant reward ONCE
103```
104
1051. Use a **mediation** layer, not a single ad network — it fills inventory and raises eCPM via **real-time bidding** (waterfalls are legacy; prefer bidding-first setups). Don't hand-integrate five SDKs separately. LevelPlay is Unity's mediation (formerly ironSource).
1062. **Rewarded ads**: grant the reward only in the `onUserEarnedReward` / completion callback, exactly once. Never grant on "ad opened" or on the close callback.
1073. **Preload** interstitials/rewarded ahead of the moment you show them; a cold request at the show point fails to fill and feels broken.
1084. Respect **ATT (App Tracking Transparency)** on iOS and **consent (UMP/GDPR/CMP)** before initializing ad SDKs, or you violate policy and lose fill.
1095. Attribution is privacy-preserving now: **AdAttributionKit** (successor to SKAdNetwork) on iOS, **Privacy Sandbox Attribution Reporting** alongside GAID on Android. Don't build UA measurement on device-ID fingerprinting.
1106. Don't interrupt active gameplay with interstitials; show at natural breaks (level end), and cap frequency.
111
112### 5. Wire Social Services (Game Center / Play Games)
113
114Use **Play Games Services v2** on Android — v1 sign-in is shut down; v2 does automatic sign-in at launch with no consent screen for basic auth.
115
116| Capability | Game Center (iOS) | Play Games Services v2 (Android) |
117|---|---|---|
118| Sign-in | `GKLocalPlayer.authenticate` | `GamesSignInClient` / one-tap |
119| Achievements | `GKAchievement` (percent → 100 = unlocked) | incremental or standard, defined in console |
120| Leaderboards | `GKLeaderboard` submit/load | `LeaderboardsClient` submit/load |
121| Cloud saves | iCloud / GKSavedGame | Snapshots API (handle conflict resolution) |
122
1231. Define achievements/leaderboards in **App Store Connect / Play Console first**; the API only references IDs that already exist there.
1242. Authenticate **early and silently**; degrade gracefully if the user declines or is offline — never block game entry on a social sign-in.
1253. For cloud saves, you **must** implement conflict resolution (two devices, divergent saves). The Snapshots/GKSavedGame API surfaces conflicts; don't blind-overwrite.
126
127### 6. Prepare for Store Submission
128
1291. **iOS**: app must have at least one IAP submitted **with the app's first review** if monetization is core; provide a **sandbox tester** account flow; privacy nutrition labels and ATT usage string are mandatory.
1302. **Android**: upload a **signed AAB**; create products in Play Console (they're inactive until the app is published to a track); use **license testers** for unpaid sandbox purchases.
1313. **Stay on the platform treadmill**: Play raises the required **target API level** every August; Apple raises the minimum **Xcode/SDK** every spring. A store-compliant build today is rejectable next year without touching your code.
1324. **Alternative billing / external purchase links** (EU DMA, Google user-choice billing, US anti-steering entitlements) are region- and program-gated compliance work — don't treat them as the default flow, and keep the standard store flow working everywhere.
1335. Test purchases in **sandbox/test tracks** before production — real charges in review get the build rejected.
134
135## Pitfalls
136
1371. **Client-side entitlement**: granting the item because the client SDK said "purchased." Always validate on a server you control.
1382. **Not consuming consumables**: user buys 100 gems once and can never buy again. Consume after grant.
1393. **No restore path**: Apple rejects apps with non-consumables/subscriptions that lack Restore Purchases.
1404. **Ignoring the Google acknowledge window**: unacknowledged purchases auto-refund in 3 days — the user is charged then refunded and you look broken.
1415. **Granting rewarded reward on the wrong callback**: granting on close instead of `onUserEarnedReward` lets users skip the ad and still get paid.
1426. **Initializing ad SDKs before consent/ATT**: policy violation, lost fill, possible removal.
1437. **Trusting receipt fields blindly**: always re-verify bundle/package id and product id against your catalog; check for replayed transaction ids.
1448. **Hardcoding prices**: always show the **store-returned localized price**, never a string you typed — currencies, tiers, and taxes vary by region.
1459. **Blocking launch on social sign-in**: make Game Center/Play Games optional and async.
14610. **Using Play Games Services v1**: v1 sign-in is shut down. Use v2 only.
14711. **Using StoreKit 1 / `/verifyReceipt`**: deprecated. Build on StoreKit 2 and JWS signature verification.
14812. **Stale Play Billing Library major**: Play blocks updates on outdated majors. Track the yearly minimum bump.
149
150## Verification
151
152- [ ] Every purchase is verified **server-side** before entitlement is granted.
153- [ ] Consumables are consumed/finished after grant; non-consumables & subs support Restore.
154- [ ] Google purchases are acknowledged within 3 days; Apple transactions finished after server confirm.
155- [ ] Transaction ids / purchase tokens are persisted and replay is rejected.
156- [ ] Rewarded reward granted exactly once in the earned-reward callback.
157- [ ] ATT (iOS) and consent (UMP/GDPR) handled before ad SDK init.
158- [ ] Achievements/leaderboards exist in the store console before the API references them.
159- [ ] Cloud saves implement conflict resolution.
160- [ ] Localized store prices are displayed, not hardcoded strings.
161- [ ] Purchases tested in sandbox / license-tester tracks before production.
162- [ ] Play Games Services v2 used (not v1) on Android.
163- [ ] StoreKit 2 used (not StoreKit 1) on iOS.
164- [ ] Play Billing Library on the current major version.
165
166## Related Skills
167
168- `mobile-development` — Godot engine-side export, signing, and the in-engine billing/ads plugins this contract sits behind.
169- `steamworks-sdk` — The PC/Steam equivalent for ownership, achievements, leaderboards, and Cloud.
170- `stripe-integration` — Web/server payments when selling outside the mobile stores.
171- `console-porting-certification` — Console store and online service equivalents when porting beyond mobile.
172
173## References
174
175- Apple StoreKit 2, App Store Server API, and App Store Server Notifications v2 documentation.
176- Google Play Billing Library and Google Play Developer API (purchases & subscriptions) documentation.
177- Google Mobile Ads (AdMob) mediation, Unity LevelPlay, and AppLovin MAX integration guides.
178- Apple AdAttributionKit and Android Privacy Sandbox Attribution Reporting documentation.
179- Apple GameKit (Game Center) and Google Play Games Services v2 documentation.