Devlog

Why Ads Must Wait for User Consent

Making Games with AI · Part 15

Making Games with AI, part 15: Why Ads Must Wait for User Consent. Historical Kibble Street TD screenshots and development diagrams.

This article revisits development in June–July 2026 and early August, using records through August 3, 2026. References to “current” behavior, values, images, candidates, and validation describe that historical snapshot, not today's released game.

Previous: Why Purchase Success Is Not Fulfillment

It is easy to assume that ad privacy starts when an ad covers the game screen. Ad services can start working much earlier: initializing at launch, connecting to servers, reading configuration, and preloading content. Requests may already have happened before the player sees anything.

For Kibble Street TD, the first question was when the ad service was allowed to start. Initializing first and presenting a consent form afterward can produce the right-looking interface with the wrong request order.

Ads start working before they appear

The startup flow first updates consent information through Google UMP. When the region and status require a form, it is loaded and presented. Google Mobile Ads starts, and preloading begins, only when UMP permits ad requests.

The consent gate precedes ad-service initialization
The consent gate precedes ad-service initialization

The gate is canRequestAds, rather than whether a popup appeared. A previously valid status can permit startup while consent information refreshes in the background. A new user or changed status may require a form first. No form does not automatically mean consent was skipped, and a displayed form does not automatically permit ad requests.

If permission remains unavailable, the normal path returns an explicit failure without starting ads. Ad initialization runs alongside game startup, so its failure is logged while the player can still reach Home and battle.

Ads are optional. Their failure must neither bypass privacy decisions nor prevent the offline game from starting.

UMP and ATT answer different questions

UMP handles regional consent status and ad privacy options. ATT handles cross-app tracking authorization and IDFA access. Neither substitutes for the other, and integrating UMP does not establish tracking authorization.

UMP consent and ATT tracking authorization have distinct responsibilities
UMP consent and ATT tracking authorization have distinct responsibilities

In this historical implementation, the app did not request ATT or read IDFA. Its privacy manifest declared tracking disabled and listed the data uses associated with advertising, analytics, and app functionality. This was an implementation choice for that version. Changes to dependencies, data use, or ad delivery would require another check of both declarations and platform settings.

Consent is also more nuanced than accepting personalized ads. Depending on the status, the platform may permit limited or non-personalized ads after personalization is declined. The game reads UMP's final permission instead of guessing.

The privacy entry follows regional status

Consent is not necessarily a one-time launch decision. Some regions require continued access to ad privacy options so users can review or change their choices.

Three platform states determine whether the Ad Privacy entry appears
Three platform states determine whether the Ad Privacy entry appears

Whenever Settings builds its content, it queries the requirement status. If access is required, Ad Privacy appears alongside Privacy and Terms and opens UMP's options form. If it is not required, the row is omitted. A failed or unknown query logs the error and preserves the basic legal links, without inventing a nonfunctional entry.

The same app version can therefore show different settings across regions and consent states. One observation on the developer's device cannot establish what all users will see.

Seeing a rewarded ad does not authorize a reward

The project had rewarded placements for shop rewards and doubled battle rewards. A tap starts a request; an ad appearing is not permission to grant resources. The native service must receive the platform's earned-reward callback and return a rewarded result before the business layer grants anything.

A rewarded ad needs an earned-reward result before game fulfillment
A rewarded ad needs an earned-reward result before game fulfillment

Early closure, an unready ad, another ad already showing, or load and presentation failures all return without a reward. The ad outcome and fulfillment outcome are recorded separately. Even after the platform authorizes a reward, saving resources can fail, and that is not a complete success.

Like purchases, the process receives an external fact before changing game state. Unlike a purchase, an ad does not provide an unfinished transaction that can automatically be fulfilled next launch. Reward-save failures therefore require their own observation and device testing.

An interstitial must not block the return home

The interstitial shown when leaving battle results for Home provides no reward and is not a player-initiated resource exchange. A remote switch controls it, with the client default set to off.

Interstitial failure still allows navigation to Home
Interstitial failure still allows navigation to Home

When disabled, the game neither loads nor shows it and clears any cached ad. HOME returns directly. When enabled, it can show only if ready. No fill, load failure, show failure, or an unready ad is logged, then navigation continues without an error popup.

The remote switch governs placement timing, not privacy permission. Consent must permit the service to start before remote configuration can decide whether a placement loads. Disabling a placement does not replace UMP, and enabling it cannot override UMP.

Separate testing from real ad delivery

The editor uses controlled mock ads. The simulator is forced onto platform test ad units. Only an iOS device reads the production ad configuration. That separation avoids invalid development traffic and keeps simulator success distinct from real ad availability.

Targeted checks passed for ad configuration, terminal initialization states, preload deduplication, no reward on early closure, reward-callback failures, interstitial return states, and the default-off switch. Privacy and base configuration files also passed format checks.

One pre-submission gap remained. Normal builds declared UMP, and the normal path blocked startup when canRequestAds was false. But if a build unexpectedly lacked UMP, a compatibility branch still started ads. That contradicted the release requirement to fail closed when consent support was missing and needed an explicit failure instead.

Ad checks that passed and real-environment acceptance still pending
Ad checks that passed and real-environment acceptance still pending

The snapshot also lacked device evidence for consent forms, Ad Privacy access, rewarded fulfillment, and interstitial switching and closure. Backend configuration was not claimed as accepted. Code contracts, simulated flow, and actual regional behavior remained separate conclusions.

What the human and AI each contribute

AI can trace consent updates, service startup, preloading, presentation, and reward callbacks, checking whether any failure branch still requests ads. It can compare placement states and events to find rewards granted on closure or navigation blocked by interstitial failure.

The human defines which ads are voluntary exchanges, which placements may be absent, whether the version requests tracking, and what region and device evidence is sufficient. Privacy and advertising settings still need verification in the actual account environment.

If you want to start

Locate ad initialization in the startup code and identify the permission gate before it. Draw separate flows for rewarded and interstitial ads: who starts them, which result permits a reward, whether navigation survives failure, and where users can reopen privacy choices.

Verify at least four states: a first launch requiring a form, an existing valid status, no permission to request ads, and a required privacy-options entry. Keeping those paths distinct is the beginning of a reliable integration.