DEV Community

Cover image for 2 Weeks to Ship 3 Buttons on iOS
Richard Andrews
Richard Andrews

Posted on • Originally published at habitdoom.com

2 Weeks to Ship 3 Buttons on iOS

Three buttons. Monthly, Yearly, Lifetime. That is all I needed to add to Habit Doom, an iOS app that [locks your distracting apps until you do your habits (https://habitdoom.com/blog/how-habit-doom-works).

The code took two days. Getting those buttons live on the App Store took two weeks.

The Bug

I had version 1.4 live on the App Store. I renamed it to v1.5 in App Store Connect to submit it with in-app purchases. The rename went through fine.

Except the “In-App Purchases and Subscriptions” section was gone. Not collapsed. Not behind a toggle. Gone. The entire section where you attach IAPs to a version for review had vanished from the page.

IAP section: gone The entire section vanished from App Store Connect
I assumed I had done something wrong. So I created a fresh version, v1.6, via “+ Version or Platform.” New version, clean slate.
Still missing.

v1.7. Missing. v1.8. Missing. v1.9. Missing.

Different browsers. Cache cleared. Different Apple IDs. Nothing worked. Four versions, same hole in the page.

## Apple Support

I was about to file a support case. But by that time a new bug showed up.

The EU Digital Services Act compliance form had its own bug, an infinite loading spinner that never resolved. A separate support case. A separate wait.

One UI bug was now blocking three revenue streams: Monthly, Yearly, and Lifetime. My app was live. Users were downloading it. And I could not charge money because Apple’s website was broken.

Then this email landed:

Email of a user describing their problem

A user reporting that the purchase button does not show up and keeps loading, even after reinstalling<br>
  the app

This is what they saw: the paywall loaded, but there were no purchase buttons. Just an infinite spinner where the pricing should be.

The API Detour

After a week of dead ends, I tried bypassing the web UI entirely using the App Store Connect REST API. I generated an API key, looked up my Lifetime purchase’s inAppPurchaseV2 ID, and submitted it programmatically.

The API accepted it. The Lifetime IAP went into review alongside v1.7. I thought I had found the fix.

I was wrong.

The Real Problem

When v1.7 shipped and I tested the live purchase flow, nothing worked. StoreKit returned zero products. The paywall was empty.
The reason: my code used com.unmanagedboy.habitdoom.monthly but App Store Connect had com.unmanagedboy.habitdoom.pro.monthly. An extra .pro. in the path. A typo I made when creating the products two weeks earlier.
Here is the thing about product IDs in App Store Connect: you cannot change them. Ever. Once created, they are permanent. The only option is to create entirely new products.
So the API workaround had submitted the wrong product. The Monthly and Yearly API submissions had also failed with DEVELOPER_ACTION_NEEDED. A week of work on the API, wasted.
Product IDs are forever You cannot change them in App Store Connect. Get them right the first time.

What Actually Fixed It

I created three brand new products with the correct IDs:

product ids

Each one needed pricing across 175 territories, localization, review screenshots, subscription group setup, and a 14-day free trial offer for Yearly.

Then I created a fresh version (v1.10) and the IAP section appeared. Just like that. The section that had been missing for a week across four different versions was suddenly there, working perfectly.
I attached all three IAPs through the UI. Submitted for review. Approved in less than 24 hours.

The old v1 products sit abandoned in App Store Connect with “Developer Action Needed” status. A monument to a two-week detour caused by one misplaced .pro. in a product ID.

Lessons

  1. Product IDs are permanent. Copy-paste them from your code into App Store Connect. Do not type them.
    One typo means recreating everything from scratch.

  2. The first IAP submission must be linked to a binary. When you submit IAPs or subscriptions for the
    very first time, they need to be attached to an app version with a binary. After that first approval, they
    can be managed separately. This is easy to miss and not obvious from the UI.

  3. Do not remove your app submission after attaching IAPs. If you have already submitted a version
    with IAPs attached and you pull or remove the app submission, the IAPs get detached and you are back to
    square one. Submit once and leave it alone.

  4. Local StoreKit testing hides ID mismatches. Your .storekit config file has its own product IDs.
    Tests pass perfectly while the live configuration is completely wrong. Test against the sandbox, not just
    the local config.

  5. Do not rename versions in ASC. Always create fresh ones via "+ Version or Platform." Renaming
    triggered the vanishing IAP section for me.

  6. If the IAP section is missing, try creating new products. In my case, creating fresh products with
    new IDs made the section reappear. No API workaround needed.

  7. The code is the easy part. StoreKit 2 is genuinely well-designed. The App Store Connect
    configuration, agreements, tax forms, and UI bugs are what eat your time.

  8. Budget two weeks for IAP integration, not two days. The code is fast. Everything around it is slow,
    broken, or both.

For a company that makes $100 billion a year from the App Store, a broken IAP section is a rounding error. For a solo developer with82 downloads and $0 in revenue](https://habitdoom.com/blog/what-82-ios-downloads-taught-me), it was a gut punch.

Habit Doom is live on the App
Store
. All three buttons work. It
just took two weeks to ship them.

Top comments (0)