What was at stake
Nobody should be asked to allow tracking before the app knows their age.
GoodBarber builds thousands of iOS apps from one engine. Depending on its owner’s choices, an app can show ads, measure its audience with analytics tools, measure which ad campaigns bring people in, and use location.
Since iOS 26, an app can ask iOS for a person’s age range, such as “under 16” or “16 or over”, without ever seeing a birthday. Some regions now require apps to check age. App owners can turn on age protection. When it is on, a person under 16 gets the app without third-party ads, third-party analytics, location, or Apple’s tracking prompt.
My responsibility — the age check and the order of the privacy steps. I built the age check, put it first in the launch sequence, reordered Google’s consent form and Apple’s tracking prompt behind it, and added the age check to ads, analytics, attribution, location, comments, sign-up, and the parental gate. A teammate added it to the chat and member list screens. The consent form and its settings existed before this work; I changed their order.
The launch order
When a GoodBarber app launches, its content and the person’s account load first. Then the privacy steps run one after the other, and each one waits for the answer of the one before.
1. Ask for the age range
When age protection is on, the app asks iOS for the person’s age range, with one threshold: 16. iOS shows its own sheet, and the person chooses whether to share. The app only asks which side of 16 the person is on.
The app asks at every launch. On iOS 26.2 and later, it first asks iOS whether the person is in a region that requires an age check. If not, nothing is shown, and the person counts as 16 or over.
When the answer is unclear, the app takes the careful side:
if age protection is off, or iOS is older than version 26: treat the person as 16 or over, without askingif iOS says no age check is required for this person: treat the person as 16 or over, and save itask iOS for the age range, with the threshold at 16if the person shared a range that starts at 16 or more: treat them as 16 or over, and save itif the person shared a range that starts below 16: treat them as under 16, and save itif the person declined, or iOS could not answer: use the answer saved at an earlier launch if there is none: treat them as under 16 show "Age verification not possible"That message tells the person that some features will be unavailable, and suggests entering their age in their App Store account.
For a person under 16, the launch sequence stops here. Nothing after this step runs.
2. Refresh Google’s consent
For everyone else, the app refreshes Google’s consent information. Google’s consent form asks the person what ads and analytics may do with their data. Google decides whether this person must see it, based on where they are, for example in Europe. The app owner can also turn the form off.
The refresh runs even when the form is off. Google’s SDK only reports that ads may be requested after a refresh, so skipping it silently blocks every Google ad.
When the person’s consent is more than 13 months old, the app asks for it again.
3. Ask to track only when it applies
Apple’s tracking prompt (App Tracking Transparency) asks whether the app may follow the person across other companies’ apps and websites. Google’s consent and Apple’s prompt answer two different questions: may ads be requested at all, and may this person be tracked. A person can refuse tracking and still see ads that are not personalized.
The prompt appears only when it can change something:
if the person is under 16: never askif the consent step failed: do not askif the person answered the form without accepting personalized ads: do not askif the app has no ads, or no tracking explanation for iOS: do not askif the person already answered the prompt once: do not ask again, and keep that answerotherwise: show Apple's tracking promptAccepting personalized ads means two choices in the form: building an ads profile, and choosing ads from that profile. When no form is required, or the owner turned it off, that check is skipped.
Only this step, and the “Update my consent” setting, can show Apple’s tracking prompt. Both refuse a person under 16. The ads SDK and the attribution tool used to ask for tracking on their own. I removed those requests so the prompt has one owner.
If the person refused tracking earlier, “Update my consent” does not ask again. It offers to open iOS Settings, the only place where that answer can change.
4. Start ads, then ask for the rest
Once the consent step has answered, the ads SDK starts, but only if Google says ads may be requested. Then comes the notification prompt, after the app’s welcome screens if it has any. Location comes last: from the moment the app launches, it cannot ask for location permission until the notification prompt has been answered.
Every feature checks again
The launch order alone is not enough. An ad can load, an analytics event can fire, and a screen can ask for location long after launch, or before the privacy steps have finished. So each feature checks the age answer itself, every time it runs. Until this launch’s answer arrives, that is the answer saved at the last launch.
| Feature | Person under 16 | Everyone else |
|---|---|---|
| Ads | Ad networks are skipped. Only the app’s own campaigns, served by GoodBarber, can show | Google’s ads load only once Google allows ads to be requested |
| Third-party analytics | Not started, and sent no events | Started; Firebase also follows the choices made in the consent form |
| Attribution, which tells the owner what brought a person in | Not started | Waits up to a minute for Apple’s tracking answer, and uses the advertising identifier only if tracking was allowed |
| Location | Never asked; the app behaves as if location were off | Asked last at launch, and used only with permission |
| Comments, member list, sign-up | Off, unless the app owner allows them for people under 16 | As the app owner set them |
| Chat | Closed | As the app owner set it |
| Purchases, sharing, some links | A parental gate asks for a simple calculation first | No gate, except in apps made for children |
Trade-offs
- Each feature checks for itself. The same question is asked in many places, and a new feature has to remember to ask it: nothing central enforces it. In return, no ad, event, or location request depends on when it happens to run.
- The saved answer is used until the new one arrives. Content and ads never wait for the age sheet. But a tool started from an earlier “16 or over” keeps running for the rest of the session if the new answer is “under 16”: from then on, the app only stops sending it events.
- Unclear answers count as under 16. Someone who is 16 or over, declines to share, and has no earlier answer saved loses location, chat, and whatever the owner turned off for people under 16, until they share their age range.
- Early iOS 26 versions ask everyone. The region check needs iOS 26.2 or later. On iOS 26.0 and 26.1, the app asks every person for their age range when age protection is on.
History
- Rewritten in plain language.
- Published