Skip to content
WebViewGold Vibe Coding to App Store
English
Get WebViewGold

Claude Code + privacy

Account deletion and data export with Claude Code: pass Apple 5.1.1(v) and Google Play

If users can create an account in your app, Apple and Google both require that they can delete it from inside the app, and Google also wants a web page for deletion requests. Claude Code can build the feature in an afternoon, but only after it knows where every piece of user data lives. This guide starts with that data map, then builds deletion, a download-my-data export and the cleanup inside the WebViewGold app.

From $109 one-time per platform, or let our team do it all from $698.

  • Approval guarantee – or money back within 14 days
  • No coding needed
  • One-time payment, free updates
  • 24/7 human support
  • Made in Germany since 2014 · ISO 27001

What the stores actually require

Apple, guideline 5.1.1(v): if your app supports account creation, users must be able to initiate account deletion within the app. Apple's guidance asks for deletion of the account record and the associated personal data, not a deactivation switch; you may keep data you are legally required to keep, and you should tell users how long deletion takes. If you offer Sign in with Apple, revoke the user's tokens through Apple's REST API when the account is deleted. Subscriptions bought through Apple are not cancelled by deleting the account, so tell users how to cancel.

Google Play: apps that let users create accounts must offer deletion inside the app and a web link where users can request deletion without reinstalling the app. You enter that link in the Data safety form, and the deletion must cover the data associated with the account, apart from what you disclose as retained. The Google Play account deletion guide covers the console side.

Data export: neither store requires it, but privacy laws such as the GDPR give users a right of access and portability, and a Download my data button answers those requests without a support ticket. It is also a good test of your data map: if the agent cannot export it, it probably cannot delete it either.

What Claude Code does and what you do

AreaClaude CodeYou
Data mapSearches code, migrations, SDK imports and webhooks in plan mode and drafts DATA_MAP.mdAdd what the code cannot show (spreadsheets, support inbox, manual exports) and confirm retention periods
CodeSettings UI, export and delete routes, cleanup helpers, migrations, tests, /delete-account pageReview, set environment variables on the host, deploy
Store consolesDrafts the privacy policy changes and the Data safety answersEnter the deletion URL in the Play Console, update App Privacy in App Store Connect
WebViewGoldNothing required; can set the downloader options if the projects are in the repositoryOne rebuild if you change downloader settings

Prompt 1: the data map, in plan mode

Plan mode lets Claude Code read and search the repository without editing anything. Save the result as DATA_MAP.md and correct it before you continue; this file is what makes the deletion complete.

Paste into Claude Code in plan mode (Shift+Tab)
Plan mode only, do not change any files. We need in-app account deletion (Apple guideline 5.1.1(v) and the Google Play account deletion policy) and a download-my-data export. First build a complete data map.

Search the codebase, the migrations, environment variable names, SDK imports, cron jobs and webhook handlers, and list every place where data about a user lives: auth records, every table with a user_id, owner_id or email column and how it references the user, storage buckets and file paths, Stripe customers and subscriptions, RevenueCat customers, OneSignal subscription IDs, Sign in with Apple tokens, analytics and error tracking, email and newsletter tools, logs and backups.

For each entry give: where it lives, which identifier links it to the user, how to delete it (foreign key cascade, API call, or retention with a reason), and whether it belongs in the export. Mark everything you are unsure about. Present the result as a markdown table I can save as DATA_MAP.md.

I am very happy I bought this app! Extremely easy and great documentation. Was in contact with the customer service, they replied very quickly and very friendly. They solved my question within a day. 10/10 would recommend.

Nelis Geiger · CodeCanyon

A typical data map for a Supabase app

DataHow it is deletedIn the export?
Auth userauth.admin.deleteUser, last stepID, email, created date
Profile and content tablesForeign keys to the user with ON DELETE CASCADEYes
Uploaded filesStorage API, per user folder (listing is not recursive)Links or the files
Stripe customer and subscriptionsCancel subscriptions; keep invoices as legally required and say so in /privacyPlan and invoice list
App Store / Google Play subscriptionCannot be cancelled by you; show cancelinapppurchase:// inside the appPlan name
RevenueCat customerRevenueCat REST API customer deletionNo
OneSignal subscription IDsDelete your stored rows; optionally the OneSignal user via their APINo
Sign in with AppleRevoke the token at Apple's revoke endpointNo
Analytics, error tracking, email toolsVendor deletion API or documented retentionUsually no

Prompt 2: build deletion and export

Switch back to the default permission mode so you can review each edit, or to accept-edits mode if you prefer to review the full diff at the end.

Paste into Claude Code after DATA_MAP.md is correct
Implement account deletion and data export based on DATA_MAP.md. Our app also runs inside native iOS and Android apps built with WebViewGold (the user agent contains WebViewGoldApp).

1. Settings > Account: a Download my data button and a Delete account button.
2. Export: GET /api/account/export returns one JSON file for the signed-in user with every exportable entry from the map, sent with Content-Type application/json and Content-Disposition attachment; filename=my-data.json. Trigger it with a normal link to that URL, not with a Blob or createObjectURL download: inside the app, the WebViewGold downloader reacts to file extensions and Content-Disposition headers. If an export can be large, build it in a background job and email a signed link that expires after 24 hours.
3. Delete: a confirmation screen that explains what is deleted, what we keep for legal reasons (invoices) and that App Store or Google Play subscriptions are not cancelled automatically. Inside the app, show a Manage subscription link that navigates to cancelinapppurchase:// when the user has a store subscription. Require typing DELETE.
4. POST /api/account/delete: authenticate, then in this order cancel Stripe subscriptions, delete the RevenueCat customer, revoke Sign in with Apple tokens if we have them (Apple REST API, /auth/revoke), delete storage files, delete rows (prefer ON DELETE CASCADE; add a migration where it is missing), and delete the auth user last with the admin client. Server-side only; the service-role key must never reach the client bundle. Make the route idempotent so a retry after a partial failure completes the job.
5. After success: sign out and show /account-deleted. Inside the app, its Done button navigates to reset:// to clear the cookies and cache the wrapper keeps.
6. A public /delete-account page for people who no longer have the app: explains the in-app path and offers a request form or an email address, works without login and on a 320 px screen.
7. Update /privacy with the retention periods and the /delete-account URL.
8. Tests for the delete route: a user with data in every table ends with zero rows, and calling the route a second time still succeeds.

Report the changed files, the migrations and every manual step I have to do.

The deletion route, in the order that does not lose IDs

Third parties first, while you still know the customer IDs; the auth user last, because most foreign keys hang off it. The helpers in account-cleanup wrap the Stripe, RevenueCat and Apple calls from your data map.

typescript
// app/api/account/delete/route.ts  (server only)
import { NextResponse } from "next/server";
import { createClient as createAdmin } from "@supabase/supabase-js";
import { createClient } from "@/lib/supabase/server";
import { cancelStripeSubscriptions, deleteRevenueCatCustomer, revokeAppleTokens } from "@/lib/account-cleanup";

export async function POST(req: Request) {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) return NextResponse.json({ error: "unauthorized" }, { status: 401 });

  const { confirm } = await req.json();
  if (confirm !== "DELETE") return NextResponse.json({ error: "confirmation missing" }, { status: 400 });

  const admin = createAdmin(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);

  // 1. Third parties, while the IDs still exist (each helper is a no-op if there is nothing to do)
  await cancelStripeSubscriptions(user.id);
  await deleteRevenueCatCustomer(user.id);
  await revokeAppleTokens(user.id);

  // 2. Files: list() is not recursive, nested folders need their own pass
  const { data: files } = await admin.storage.from("uploads").list(user.id);
  if (files && files.length > 0) {
    await admin.storage.from("uploads").remove(files.map((f) => user.id + "/" + f.name));
  }

  // 3. Rows go with the user through ON DELETE CASCADE (see DATA_MAP.md)
  // 4. The auth user, last
  const { error } = await admin.auth.admin.deleteUser(user.id);
  if (error) return NextResponse.json({ error: "delete failed, safe to retry" }, { status: 500 });

  return NextResponse.json({ ok: true });
}

Make the export download inside the app

Two small settings decide whether the file reaches the phone.

  1. Serve a real file URL

    The route above returns JSON with a Content-Disposition attachment header. Link to it with a plain anchor; JavaScript-generated Blob downloads are not covered by the WebViewGold downloader docs.

  2. iOS

    Either enable autodownloader in Config.swift (downloads based on Content-Disposition headers) or serve the file under a URL ending in .json and add ".json" to extentionARY. See the iOS file downloader docs.

  3. Android

    Enable AUTO_DOWNLOAD_FILES in Config.java or add the extension to downloadableExtension; requireStorage must stay true if you use downloads. See the Android file downloader docs.

  4. Rebuild once

    These are native settings, so they need one new build. Everything else in this guide ships with your next web deploy. The Cloud Builder can produce that build without a local Xcode or Android Studio setup.

Verification checklist

  • In the TestFlight and internal testing builds, create a fresh account, add content, upload a file and, if you sell subscriptions, buy one in the sandbox.
  • Tap Download my data: the file arrives on the phone and contains your content, not an empty object.
  • Tap Delete account: the confirmation explains consequences and the subscription note, the Manage subscription link opens the store screen, typing DELETE completes the flow and the app shows the confirmation.
  • Tap Done on the confirmation: reset:// clears the wrapper's cookies and cache. Note what your build shows afterwards and make sure it is a clean start, not an error.
  • Try to sign in again: the account no longer exists. A query for the user ID returns zero rows in every table from DATA_MAP.md, and the storage folder is empty.
  • For a Sign in with Apple test user, the app disappears from the Sign in with Apple list in that Apple Account's settings after deletion, which shows the token was revoked.
  • Open /delete-account in a private browser window on a phone: it works logged out, and the same URL is in the Play Console Data safety form.

Pitfalls

  • Soft delete only. A deleted_at flag is deactivation. Reviewers and Google expect the data to be gone, apart from disclosed retention.
  • Deleting the auth user first. Without cascades, rows remain; with cascades, you lose the IDs you needed for Stripe and RevenueCat. Third parties first, auth last.
  • Forgotten storage. Avatars and uploads survive row deletion. The data map exists to catch exactly this.
  • Deleting the reviewer's demo account. Reviewers may test deletion on the account you gave them. Say in the review notes that they can sign up fresh, and re-create the demo account after each review.
  • Hidden behind support. "Email us to delete your account" as the only path fails 5.1.1(v) for most apps. The in-app button must start the deletion.

Frequently asked questions

Is deactivating the account enough?

No. Apple asks for deletion of the account and its associated personal data, and Google Play requires the data to be deleted, not just hidden. Deactivation can be an extra option, not the only one.

Can I keep some data after deletion?

Yes, where you have a legal obligation or a legitimate reason, such as invoices for tax law. Disclose it in your privacy policy and in the Data safety form.

Can deletion take a few days?

A short grace period is common. Start the deletion in the app, tell the user exactly when the data will be gone, and check Apple's current account deletion guidance for the wording reviewers expect.

What happens to subscriptions bought in the app?

You cannot cancel App Store or Google Play subscriptions on the user's behalf. Show a Manage subscription link (cancelinapppurchase:// inside the app) and say clearly that billing continues until they cancel.

Which format should the export use?

A structured, machine-readable format such as JSON or CSV. One JSON file per account is the easiest to generate, test and explain.

Three ways to get your app into the stores

Same result, different amount of work on your side. All three come with the approval guarantee and 24/7 human support.

Do it yourself

$109 per platform, one-time

The WebViewGold license: a finished Xcode or Android Studio project. Paste your URL, set name and icon, switch on features, build and submit. Free updates forever.

See plans on the main page

Cloud Builder

$349 per license, one-time add-on

No Mac, no Xcode, no Android Studio: configure in the browser, we build both apps in the cloud and hand them to App Store Connect and the Play Console.

How the Cloud Builder works Try the free demo

Full Service

$698 per platform $798

Send us your URL and icon. Our team configures, builds and delivers your app within 72 hours, white-label, with source projects. Both platforms for $1,158.

Full Service details Powered by WeSetupYourWebViewApp

Winter Sale prices valid until December 31, 2026.

Ready to ship your app?

App Store & Google Play approval guarantee – or your money back within 14 days

Rather hand it over? Full Service: we configure, build and deliver within 72 hours, from $698 per platform. Questions? Chat with us 24/7.

Refunds are granted under the conditions listed in our FAQ: a non-content rejection by Apple and/or Google, claimed within 14 days after purchase.