The Play Store gauntlet
Everything between a finished app and a live listing: store assets, data safety, content rating, the target-audience trap, app-ads.txt, and the testing tracks, from real experience.
The code was done. Then I met the Play Console. If you have only ever shipped to the web, the amount of non-code work to publish a mobile app is a genuine surprise. Here is the checklist I assembled the hard way, four times.
Store listing assets
- Icon 512 by 512. Feature graphic 1024 by 500. At least two phone screenshots.
- The feature graphic is the one people skip. I generated all four with a small Python script (Pillow): a brand-color gradient, the app icon, the title in the app's font, a faint crossword motif. Code is a perfectly good design tool when you need four on-brand banners fast.
- Short description (80 chars) and full description (4000). Write them for the audience, not for a checklist. Mine are casual Bahasa Indonesia, because that is who plays.
Data safety, honestly
The Data safety form asks what data you collect. The honest answer for these apps: nothing I store, but the SDKs collect things. AdMob takes an advertising ID and coarse location, Sentry takes crash diagnostics, RevenueCat handles purchase data. All of it is "collected and shared", encrypted in transit, not user-deletable in-app. Declare it accurately; Google cross-checks it against your privacy policy.
The target-audience trap
This one nearly cost me. In "Target audience and content", I had ticked an age band that included under-13. That silently opted the app into Google's Families policy, which requires a certified child-safe ad SDK and non-personalized ads only. The fix was to set the minimum target age to 13+. Content rating can still be "Everyone / 3+"; those are different fields. If you are not deliberately making a kids app, do not let the target-audience picker turn you into one.
app-ads.txt
Advertisers verify your ad inventory by fetching app-ads.txt from the developer
website on your store listing. One line:
google.com, pub-XXXXXXXXXX, DIRECT, f08c47fec0942fa0
Two gotchas: the website field on each listing must point at the domain that
serves the file, and the file must return as plain text with a 200, not get
swallowed by your site's 404 handler. Mine 404'd at first because it was never
actually deployed. Verify with curl, not faith.
Privacy policy
Required, and it must be live at the URL you paste, or review rejects you. Mine spells out the SDKs, the advertising ID, and a contact email for data-deletion requests. Since there is no backend, "deletion" is mostly pointing the user at uninstall and the ad-ID reset, which is a legitimate answer for an app that stores nothing server-side.
The testing tracks, and the door I used
Internal, closed, open, production. The confusing part: open testing is restricted until you have a production release, and early access (the public-beta track for unreleased apps) wanted pre-registration setup. After going in circles, I went straight to production. For a finished, tested app, that was the cleaner door. Feedback in the testing tracks is private and does not touch your public rating, which is the main reason to use them, but they are not the only path.
Real-time notifications and the 36-hour wait
Several things (RevenueCat product import, service-account validation, app-ads.txt verification) are eventually consistent on Google's side, measured in hours up to a day or two. Set them up early and do not interpret "not working yet" as "broken". Sometimes the fix is patience.
The lesson
Budget a real chunk of time for the part with no code in it. Make the listing assets early, fill the policy forms honestly, and verify the external checks (app-ads.txt, RTDN, privacy URL) with tools instead of assumptions. The app being done is the halfway point, not the finish line.
Next: what happened once real testers got their hands on it.