View as Markdownllms.txt

Reference

Privacy and data handling

AppRefer tracks only with the user's permission, hashes personal data on the device, keeps test data separate and lets your server erase a user when they delete their account.

The SDKs never show the App Tracking Transparency prompt. From SDK 0.6.0 they read the status your app already has (on Android, the consent you pass with setTrackingConsent()) and send it with the install. Matching an install to an ad click, sending conversions to ad networks and keeping advanced-matching data happen only when the user allowed tracking. Without permission an install gets Apple AdServices or organic attribution, and analytics, AppRefer Billing and Support keep working. The server checks the stored consent again on every forward and retry.

Installs that sent no consent

Installs from SDKs older than 0.6.0 send no consent status, and AppRefer treats those as allowed so existing apps keep their attribution. To treat a missing status as “not allowed”, set trackingConsentRequired: true on the app with PATCH /api/v1/apps/{appId} once every live version of your app is on 0.6.0 or later (or if older installs must never be tracked). See Tracking consent.

Requests from installs that allowed tracking go to trk.apprefer.com; everything else goes to apprefer.com, and the two never fall back to each other. In your iOS privacy manifest, declare only trk.apprefer.com in NSPrivacyTrackingDomains. How undecided installs are held, and the trackingConsentRequired and probabilisticMatching app settings, are described under Attribution.

Turning collection off

If your app has its own privacy switch, call setCollectionEnabled(false) (SDK 0.9.1+). The choice is saved on the device. It stops attribution, consent reports, conversion-value updates and product events, and clears events waiting to be sent. AppRefer Billing and Support keep working, and Billing stops sending the install's device ID. To resume, call setCollectionEnabled(true) and then configure().

await AppRefer.setCollectionEnabled(false)

When a user signs out, call reset() (SDK 0.9.0+). It clears the user's ID, queued events and Support session on the device and keeps the install's own attribution. Nothing more is sent until you call configure() for the next user.

On-device hashing

Personal data passed to setAdvancedMatching() is SHA-256 hashed on the device, so AppRefer never receives it in plain text. The SDK only sends it for installs that allowed tracking.

FieldExample inputWhat is hashed
Email User@Example.com Trimmed and lower-cased: user@example.com
Phone+1 (415) 555-1234Digits only: 14155551234
First name JohnTrimmed and lower-cased: john
Last nameDoe Trimmed and lower-cased: doe
Date of birth19900115Trimmed; pass it as YYYYMMDD

These hashes are attached to conversions for Meta and TikTok, which expect hashed values. Email, phone and name details that arrive with a RevenueCat webhook are hashed on the server in the same way, and are kept only for installs that allowed tracking.

Data retention

DataKept forPurpose
Clicks (including IP address)30 daysMatching clicks to installs
Attributions400 daysInstall-to-campaign mapping, long enough to cover yearly renewals
Forwarding retry queue30 daysRetrying failed sends to ad networks
Webhook de-duplication30 daysIgnoring repeated RevenueCat events
Held trials30 daysQualified trials
Qualified purchase results and store notices400 daysQualified purchases (observe only); ids stored as one-way hashes
Qualified purchase activity recordUp to 45 daysCounted SDK event ids and times per install, only for event names a rule counts; deleted when the user is erased
SKAdNetwork postbacks90 daysPostback validation
Audit log365 daysWho changed what
Billing events and store links400 daysPurchase idempotency and linking old app versions
Support sessions400 days after last useIn-app chat identity
Support screenshots400 days (unsent uploads: 1 day)Attachments in conversations

Records expire automatically. Aggregated analytics (installs, events, revenue) are kept in the reporting warehouse for long-term dashboards.

Test data stays separate

Data sent with a test key (pk_test_) and store sandbox purchases are kept apart from live data:

  • They are never sent to ad networks.
  • They don't appear in live dashboard views or revenue; use the Sandbox switch to see them.
  • Installs are matched separately from live installs.
  • Support conversations from test keys sit in a separate test inbox.

App Review buys with sandbox accounts in your release build, so a sandbox purchase sent with your live key still unlocks the purchase (AppRefer Billing) but is recorded as sandbox and never counted or forwarded.

SDK dependencies

No AppRefer SDK bundles another analytics or advertising SDK. The iOS SDK has no third-party dependencies. The others use only standard platform libraries:

  • Android: Kotlin coroutines, Google Play Install Referrer and the Google Play services advertising ID library.
  • Flutter: shared_preferences, http, crypto, device_info_plus, package_info_plus, intl and the official in_app_purchase plugins.
  • React Native: AsyncStorage and react-native-iap as peer dependencies.

Erasing a user (account deletion)

When someone deletes their account in your app, your server calls POST /api/v1/apps/{appId}/users/erase with an organisation API key that has the users:erase scope.

Terminal
curl -X POST https://apprefer.com/api/v1/apps/APP_ID/users/erase \
  -H "Authorization: Bearer ak_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "requestId": "del_8f3a2c91", "appUserId": "user_123" }'
FieldRequiredDescription
requestIdYesYour deletion job ID, 8 to 64 letters, digits, _ or -. Retrying with it is safe.
appUserIdYesThe user ID you set with setUserId and use for purchases.
deviceIdsNoUp to 20 device IDs. Each counts only if AppRefer already links it to this user.
environmentNoall (default), live or sandbox

AppRefer finds the user's devices itself, from setUserId and their events. It removes their attribution records, queued conversions, held trials, support conversations, the support context your backend sent and AppRefer Billing identity straight away and answers 202. Rows in the reporting warehouse follow within a few hours, once recent rows can be changed. Check progress with GET /api/v1/apps/{appId}/users/erase/{requestId}.

  • Analytics events become anonymous counts: no user, device or session ID, no properties, and the time cut to the day, so they no longer link to each other or to anyone.
  • Accounting records (payments, refunds, renewals, trial starts and the billing ledger) keep their amounts, dates and products, with the user replaced by a keyed one-way stand-in. They are never listed in the dashboard or API, and are deleted seven years after their date, which covers the six years after the end of the financial year that tax record-keeping rules require.
  • App settings, links and integrations are never touched. Conversions already sent to ad networks can't be recalled.
  • Reusing a requestId for a different user returns 409. 30 days after the job finished AppRefer forgets the request and returns 409 REQUEST_ID_EXPIRED.

Live and sandbox data

By default one call erases the user's live and sandbox data together. Send "environment": "sandbox" to erase only test data (installs and support chats made with a test key, App Store and Google Play sandbox purchases), for example to clear your testers before launch, or "live" for the reverse. The value is returned on the job; anything else is a 400, and retrying a requestId with a different environment is a 409.

A sandbox-only erase never touches live data, so it keeps the records AppRefer holds once per user for both sides (the Billing customer record, account tokens and store links). Use the default if you want those gone too.

Account deletion must use the default

In-app account deletion must use all. live leaves the user's sandbox purchases, test installs and test-key chats tied to them. Use a separate requestId per environment (for example an sb_ prefix for tester clean-ups): a requestId used once with sandbox can't later be reused for the full deletion.

Your data, secured

Attribution data and ad network credentials are encrypted in transit and at rest, and integration secrets are never shown again after you save them. Your data is only sent to the ad networks and services you connect.