EEltaCrew
HomeBlog

Data safety forms with zero declarations are getting caught: auditing 21 apps and fixing them with CSV and the API

Published 2026-09-16Measured 2026-09-15About 3 min readelta · EltaCrew

A phone number the user types in by hand, belonging to someone else, still counts as "phone number collection" to Google. After one rejection I compared all 21 apps' data-safety declarations against their source: 11 were wrong, and 3 had declared nothing at all. Why ad-only apps cannot declare zero, and how to fix the form with CSV and the API instead of the five-step wizard.

One rejection

In early September 2026 an update to the pet-care app was rejected for a data-safety mismatch. The app has a field where you note a vet's phone number, and the form did not declare phone-number collection. No READ_PHONE_STATE permission, not the device's own number, a number typed by the user about someone else, and it still counts as phone-number collection under Google's definition.

While an app is rejected, other changes get bundled with it. Three store-listing edits for that app were stuck as pending because of the data-safety rejection. When you receive a rejection, check the number of pending changes in the publishing overview.

Auditing all 21

If one app is wrong, the rest are suspect. I exported each of the 21 apps' current declarations from the console as CSV and compared them with the source: permissions, SDKs, input fields. Eleven were wrong.

The three with zero declarations were ad-only apps, and I had assumed "they collect nothing". Wrong. The AdMob SDK collects approximate location (IP), app interactions, and device or other IDs, and shares them for advertising. Ad-only apps must declare those three. Miss them when registering a new app and it goes live with zero declarations.

That same evening, one of the three received a policy email for "device or other IDs not declared", with a two-week deadline. Enforcement has started, and the other two are a matter of time.

CSV instead of the five-step wizard

The console's data-safety wizard is five steps of clicking, and with 21 apps that is a day gone. At the top there are "Export to CSV" and "Import from CSV" buttons.

  1. Export: the entire current declaration comes out as CSV (782 rows × 5 columns for one app). This doubles as the backup before any change.
  2. Fill in Response value only on the rows you need.
  3. Import → review → save → submit from the publishing overview.

Adding a phone number takes five rows, following the same pattern as the existing name (PSL_NAME) rows:

PSL_DATA_TYPES_PERSONAL | PSL_PHONE | true
PSL_DATA_USAGE_RESPONSES:PSL_PHONE:PSL_DATA_USAGE_COLLECTION_AND_SHARING | PSL_DATA_USAGE_ONLY_COLLECTED | true
PSL_DATA_USAGE_RESPONSES:PSL_PHONE:PSL_DATA_USAGE_EPHEMERAL | | false
PSL_DATA_USAGE_RESPONSES:PSL_PHONE:DATA_USAGE_USER_CONTROL | PSL_DATA_USAGE_USER_CONTROL_OPTIONAL | true
PSL_DATA_USAGE_RESPONSES:PSL_PHONE:DATA_USAGE_COLLECTION_PURPOSE | PSL_APP_FUNCTIONALITY | true

Save the CSV without a BOM, with CRLF line endings. In step 4 of the wizard, a button labeled "N unanswered questions" can sit next to a status cell that says "Completed"; the status cell is the truth. Do not refill it because of the label.

Writing works through the API too

I first wrote that there was no API, then corrected myself. The Android Publisher API has applications.dataSafety(packageName, body={"safetyLabels": <entire CSV as a string>}). Edit the exported CSV and post it there, and the wizard never needs to be opened. There is no export API, so the backup still comes from the console. I have the patches for all 21 apps in one JSON file, to be applied together with the next all-app update once account-side release blocking is resolved.

Summary

Google Playdata safetypolicyPlay Console

Related

R8 on, build green, app broken: five runtime traps that actually hit across 15 appsI enabled R8 in 15 apps for Play's 2027 code-optimization requirement. Every build passed, but 2 of the first 7 I installed broke at runtime. Gson deserialization, getIdentifier resource lookups, Room _Impl classes, and debuggable builds that silently disable R8: the kinds of failure that never show up in a crash log.One merchant account blocked releases for all 21 of my apps: Korean individual developers and Play Console's "additional information required"Right after I set up a merchant account to test a donation in-app product, Play Console demanded a business registration number and an e-commerce license number and blocked every release on the account. Deleting the products did not help, deleting the payout account did not help, and support's final answer was "this cannot be reversed". How an individual developer avoids this trap.The #1 app in Play search has the query in its title, verbatim: how one middle dot killed our keyword matchingI measured 157 Korean Play search queries by hand. The top-ranked app always carried the exact query string, spacing included, in its title. Our apps had been invisible for QR queries because I had joined words with a middle dot to make the title look nicer. The evidence behind retitling 13 apps.