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.

The privacy steps at launch, in five steps. First, the app opens and loads its content and the account. Second, iOS asks for the person's age range, with the threshold at 16; for a person under 16, the sequence stops there. Third, for everyone else, Google's consent form appears where it is required. Fourth, Apple's tracking prompt appears only if it applies. Fifth, ads can start, then the app asks for notifications, then location. Ads, analytics, and location also check the age answer each time they run.

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:

Decide which side of 16 the person is on
if age protection is off, or iOS is older than version 26:
treat the person as 16 or over, without asking
if iOS says no age check is required for this person:
treat the person as 16 or over, and save it
ask iOS for the age range, with the threshold at 16
if the person shared a range that starts at 16 or more:
treat them as 16 or over, and save it
if the person shared a range that starts below 16:
treat them as under 16, and save it
if 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.

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:

Decide whether to show the tracking prompt
if the person is under 16:
never ask
if the consent step failed:
do not ask
if the person answered the form without accepting personalized ads:
do not ask
if the app has no ads, or no tracking explanation for iOS:
do not ask
if the person already answered the prompt once:
do not ask again, and keep that answer
otherwise:
show Apple's tracking prompt

Accepting 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.

FeaturePerson under 16Everyone else
AdsAd networks are skipped. Only the app’s own campaigns, served by GoodBarber, can showGoogle’s ads load only once Google allows ads to be requested
Third-party analyticsNot started, and sent no eventsStarted; Firebase also follows the choices made in the consent form
Attribution, which tells the owner what brought a person inNot startedWaits up to a minute for Apple’s tracking answer, and uses the advertising identifier only if tracking was allowed
LocationNever asked; the app behaves as if location were offAsked last at launch, and used only with permission
Comments, member list, sign-upOff, unless the app owner allows them for people under 16As the app owner set them
ChatClosedAs the app owner set it
Purchases, sharing, some linksA parental gate asks for a simple calculation firstNo 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

  1. Rewritten in plain language.
  2. Published