Skip to content

AppPrivacy

Joseph Samir edited this page Jun 21, 2026 · 2 revisions

App Privacy & Data Collection

The Convert iOS SDK collects no personally identifiable information on its own. The only identifier it generates locally is an app-scoped UUID used for experiment bucketing, stored in the Keychain (system of record) with a UserDefaults mirror for fast reads. Events sent to Convert contain: the visitor id (the UUID), any segments you set, and experiment/goal identifiers. No device identifiers, no advertising identifier (no IDFA, no IDFV), no location data, no contacts, no user-profile data.

This page maps the SDK's data behavior onto Apple's App Privacy questionnaire (App Store Connect) and explains every entry in the shipped PrivacyInfo.xcprivacy Apple Privacy Manifest.

You remain responsible for declaring any user-derived data you pass into the SDK.

Apple Privacy Manifest (PrivacyInfo.xcprivacy)

The SDK ships Sources/ConvertSwiftSDK/Resources/PrivacyInfo.xcprivacy as a .process-type resource that Xcode bundles into your app's manifest. Apple requires privacy manifests for SDKs designated as tracking-capable; Convert is designated as requiring one because A/B testing SDKs fall under that category.

Tracking declaration

NSPrivacyTracking = false
NSPrivacyTrackingDomains = (empty)

The SDK does no cross-app or cross-site tracking. It reads neither the IDFA nor the IDFV, shows no App Tracking Transparency (ATT) prompt, and your app does not need to call ATTrackingManager on Convert's behalf.

Collected data types

The manifest declares exactly two collected data types:

Data type (NSPrivacyCollectedDataType) What it is in Convert Linked to user Used for tracking Purposes
NSPrivacyCollectedDataTypeDeviceID The generated visitor UUID (not IDFA/IDFV) false false App Functionality, Analytics
NSPrivacyCollectedDataTypeProductInteraction Experiment exposures and goal conversions false false App Functionality, Analytics

Both are declared not linked to the user's identity and not used for tracking. The two purposes mean the same data does two jobs: App Functionality (deciding which variation to serve) and Analytics (the conversion reports you read in Convert).

Required-reason API

The manifest declares one required-reason API:

API (NSPrivacyAccessedAPIType) Reason code Why
NSPrivacyAccessedAPICategoryUserDefaults CA92.1 The SDK reads and writes UserDefaults solely to mirror the visitor identifier for fast reads — values only accessible to the app itself.

App Store App Privacy questionnaire mapping

Paste the following into your App Store App Privacy questionnaire for the portion contributed by this SDK. There are no placeholders to fill in.

Data used for tracking: None. The Convert SDK performs no cross-app or cross-site tracking. It reads no advertising identifier (no IDFA, no IDFV) and shows no App Tracking Transparency prompt.

Data collected — Device ID. The Convert SDK assigns each visitor a randomly generated UUID to keep A/B-test assignments consistent across launches. It is not an advertising identifier and is not linked to the user's identity. Used for App Functionality and Analytics. Not used to track the user.

Data collected — Product Interaction. The Convert SDK records which experiment variation a visitor was shown and which in-app goals they completed, so the experiment can run and its results can be reported. This data is not linked to the user's identity. Used for App Functionality and Analytics. Not used to track the user.

In Apple's questionnaire these map to the Identifiers → Device ID and Usage Data → Product Interaction categories, each with "Used to Track You" = No and "Linked to the User" = No.

Per-data-type declarations (SDK-generated data only)

Data type Collected Shared Purposes
Device or other IDs Yes (the visitor UUID) Yes (sent to Convert in event payloads) App Functionality, Analytics
Product Interaction (bucketing + conversion events) Yes Yes (sent to Convert) App Functionality, Analytics
Personal info No No None
Location No No Audience location rules use inputs you provide via setDefaultSegments / setCustomSegments; the SDK collects no location itself
Financial info No No Transaction values you attach via GoalData (amount, transactionId) are aggregate analytics inputs, not per-user financial records
Contacts / Messages / Photos / Audio / Files / Calendar / Health / Web browsing No No None

Data you pass in

If your app passes user-derived attributes (for example plan, country, accountAgeDays) into createContext(attributes:), setDefaultSegments(_:), or setCustomSegments(_:), those values flow through to Convert. Declare them separately on the App Privacy form according to your own privacy posture and the meaning of the data you send.

The visitor ID

The default visitor id is a version-4 (random) UUID generated on-device the first time a context is created without an explicit visitorId. It is stored in the Keychain (system of record) with a UserDefaults mirror for fast reads.

  • It is a 122-bit random value with no correlation to the user's real identity.
  • It is not the IDFA or IDFV and carries no advertising linkage.
  • It is discarded from UserDefaults on app uninstall; the Keychain copy may survive depending on your app's Keychain sharing settings.
  • If you supply your own explicit visitor id via sdk.createContext(visitorId: "your-id"), you control what that id reveals — declare accordingly on the App Privacy form.

No consent management — you own the decision

The SDK ships no consent-management UI. It does not store a consent flag, present a consent dialog, or gate itself on one. Consent is your decision to make, and you enforce it with the controls the SDK provides:

  • Don't initialize. If a user has not consented, simply do not construct ConvertSwiftSDK. No identifier is generated, no bucketing runs, no event is sent.
  • Disable delivery at init time (static). Set ConvertConfiguration(sdkKey:, networkTracking: false). Bucketing still resolves so your UI can decide, but no exposure or conversion event is ever sent.
  • Disable delivery for a single experience (per-call). Pass enableTracking: false to context.runExperience(_:enableTracking:). Note this per-call flag governs the experience path only; the feature path (runFeature/runFeatures) takes no enableTracking parameter (Android parity).
  • Disable delivery at runtime (mid-session). Call await sdk.setTrackingEnabled(false) at any point after initialization. Re-enable with await sdk.setTrackingEnabled(true) (suppressed events are not replayed). This is the supported consent-withdrawal path for GDPR mid-session opt-out.

Related pages

Clone this wiki locally