# Data Collection Overview of data collection and controls provided by the Airship SDK. # Privacy Manager > Use Privacy Manager to enable or disable Airship SDK features for privacy and consent management. Privacy Manager allows you to control which Airship SDK features are enabled. This is particularly useful for consent opt-in flows where you need to disable all features initially, then enable them as users grant consent. For information about what data is collected for each Privacy Manager flag, see [SDK Data Collection](https://www.airship.com/docs/reference/data-collection/sdk-data-collection/). When all features are disabled, the SDK operates in a no-op mode—it doesn't store data or make network requests. Once features are enabled, you can enable or disable specific features at runtime based on user consent. ## Privacy Manager flags Each Privacy Manager flag controls a group of related Airship features. Enabling a flag enables all features within that group: #### Swift | Swift Constant | Features | Config Value | |----------------|----------|--------------| | `AirshipFeature.push` | Push notifications | `push` | | `AirshipFeature.inAppAutomation` | In-App Automation, In-App Messages, Scenes, and Landing Pages | `in_app_automation` | | `AirshipFeature.messageCenter` | Message Center | `message_center` | | `AirshipFeature.tagsAndAttributes` | [Tags](https://www.airship.com/docs/guides/audience/tags/), [Attributes](https://www.airship.com/docs/guides/audience/attributes/about/), Subscription Lists, and Preference Center | `tags_and_attributes` | | `AirshipFeature.contacts` | Contact Tags, Attributes, and Subscription Lists; Named User; and Associated Channels | `contacts` | | `AirshipFeature.analytics` | Associated identifiers, Custom events, Screen tracking, Surveys (questions and NPS surveys in [Scenes](https://www.airship.com/docs/reference/glossary/#scene)), email address (via form inputs in Scenes), [Feature Flag](https://www.airship.com/docs/reference/glossary/#feature_flag) interaction | `analytics` | | `AirshipFeature.featureFlags` | Feature Flag evaluation and interaction | `feature_flags` | | `AirshipFeature.all` | All features | `all` | | `[]` | No features | `none` | #### Objective-C | Objective-C Constant | Features | Config Value | |----------------------|----------|--------------| | `UAFeatures.push` | Push notifications | `push` | | `UAFeatures.inAppAutomation` | In-App Automation, In-App Messages, Scenes, and Landing Pages | `in_app_automation` | | `UAFeatures.messageCenter` | Message Center | `message_center` | | `UAFeatures.tagsAndAttributes` | [Tags](https://www.airship.com/docs/guides/audience/tags/), [Attributes](https://www.airship.com/docs/guides/audience/attributes/about/), Subscription Lists, and Preference Center | `tags_and_attributes` | | `UAFeatures.contacts` | Contact Tags, Attributes, and Subscription Lists; Named User; and Associated Channels | `contacts` | | `UAFeatures.analytics` | Associated identifiers, Custom events, Screen tracking, Surveys (questions and NPS surveys in [Scenes](https://www.airship.com/docs/reference/glossary/#scene)), email address (via form inputs in Scenes), [Feature Flag](https://www.airship.com/docs/reference/glossary/#feature_flag) interaction | `analytics` | | `UAFeatures.featureFlags` | Feature Flag evaluation and interaction | `feature_flags` | | `UAFeatures.all` | All features | `all` | | `UAFeatures.none` | No features | `none` | ## Configuring default enabled features You can configure which features are enabled by default when the SDK initializes. This is done in your Airship config during [takeOff](https://www.airship.com/docs/developer/sdk-integration/apple/installation/getting-started/#calling-takeoff). ### Default configuration (all features enabled) By default, all features are enabled. The SDK will collect data and make network requests as configured. ### Disabling all features To disable all features by default (useful for consent opt-in flows), set the enabled features to an empty array: #### Swift **Config** ```swift let config = AirshipConfig() config.enabledFeatures = [] try! Airship.takeOff(config) ``` **AirshipConfig.plist** ```xml ... enabledFeatures ... ``` #### Objective-C **UAConfig** ```objc UAConfig *config = [UAConfig config]; config.enabledFeatures = UAFeaturesNone; [UAirship takeOff:config error:&airshipError]; ``` **AirshipConfig.plist** ```xml ... enabledFeatures ... ``` ### Enabling specific features To enable only specific features by default: #### Swift **Config** ```swift let config = AirshipConfig() config.enabledFeatures = [.push, .analytics] try! Airship.takeOff(config) ``` **AirshipConfig.plist** ```xml ... enabledFeatures push analytics ... ``` #### Objective-C **UAConfig** ```objc UAConfig *config = [UAConfig config]; config.enabledFeatures = UAFeaturesPush | UAFeaturesAnalytics; [UAirship takeOff:config error:&airshipError]; ``` **AirshipConfig.plist** ```xml ... enabledFeatures push analytics ... ``` ### Resetting features on each app start If you need to gather consent on each app start, enable `resetEnabledFeatures` to reset enabled features to the config defaults on each `takeOff`, ignoring any previously persisted settings: #### Swift ```swift var config = AirshipConfig() config.enabledFeatures = [] config.resetEnabledFeatures = true try! Airship.takeOff(config) ``` #### Objective-C ```objc UAConfig *config = [UAConfig config]; config.enabledFeatures = UAFeaturesNone; config.resetEnabledFeatures = YES; [UAirship takeOff:config error:&airshipError]; ``` ## Modifying enabled features at runtime You can enable or disable features at any time after takeOff. Once you modify the enabled features from the default, those settings are persisted between app launches (unless `resetEnabledFeatures` is enabled in your config). ### Enabling features #### Swift ```swift Airship.privacyManager.enableFeatures([.push, .analytics]) ``` #### Objective-C ```objc UAFeature *features = [[UAFeature alloc] initFrom:@[UAFeature.push, UAFeature.analytics]]; [UAirship.privacyManager enableFeatures:features]; ``` ### Disabling features #### Swift ```swift Airship.privacyManager.disableFeatures([.push, .analytics]) ``` #### Objective-C ```objc UAFeature *features = [[UAFeature alloc] initFrom:@[UAFeature.push, UAFeature.analytics]]; [UAirship.privacyManager disableFeatures:features]; ``` ## Consent opt-in flow example A common use case is to start with all features disabled, then enable them as users grant consent: #### Swift ```swift // Start with all features disabled var config = AirshipConfig() config.enabledFeatures = [] try! Airship.takeOff(config) // Later, when user grants consent: func userGrantedConsent() { // Enable features based on user's consent choices Airship.privacyManager.enableFeatures([.push, .analytics]) } ``` #### Objective-C ```objc // Start with all features disabled UAConfig *config = [UAConfig config]; config.enabledFeatures = UAFeaturesNone; [UAirship takeOff:config error:&airshipError]; // Later, when user grants consent: - (void)userGrantedConsent { // Enable features based on user's consent choices UAFeature *features = [[UAFeature alloc] initFrom:@[UAFeature.push, UAFeature.analytics]]; [UAirship.privacyManager enableFeatures:features]; } ``` > **Note:** If features are disabled after being previously enabled, the SDK may make a few network requests to opt the channel out to prevent notifications. ## Related documentation - [SDK Data Collection](https://www.airship.com/docs/reference/data-collection/sdk-data-collection/) - Comprehensive overview of what data Airship collects for each Privacy Manager flag - [Apple Privacy Manifest](https://www.airship.com/docs/reference/data-collection/apple-privacy-manifest/) - Declare data collection practices to Apple - [Analytics](https://www.airship.com/docs/developer/sdk-integration/apple/analytics/) - Track user engagement with custom events, screen tracking, and associated identifiers - [Permission Gathering](https://www.airship.com/docs/developer/sdk-integration/apple/data-collection/permission-gathering/) - Request additional permissions from users # Permission Prompts > Request additional system permissions (e.g., location) from users using Opt-in Actions.The Airship SDK automatically handles push notification permissions. For additional permissions like location, you can use Opt-in Actions to prompt users using native permission prompts. Opt-in Actions are a special type of [Action](https://www.airship.com/docs/reference/glossary/#action) that are handled by `PermissionsManager`. For an overview of all supported actions and where they are available, see the [Actions](https://www.airship.com/docs/guides/messaging/messages/actions/) guide. ## Supported Opt-in Types * Push — Handled automatically by the SDK (no implementation needed) * Location — Requires implementing a custom `PermissionDelegate` ## Implementing Location Opt-in To implement Location Opt-in, create a custom `PermissionDelegate` and register it with `PermissionsManager` to handle location permissions. ### Create a Location Permission Delegate #### Swift ```swift import Foundation import CoreLocation import AirshipCore import Combine class LocationPermissionDelegate: AirshipPermissionDelegate { let locationManager = CLLocationManager() @MainActor func checkPermissionStatus() async -> AirshipCore.AirshipPermissionStatus { return self.status } @MainActor func requestPermission() async -> AirshipCore.AirshipPermissionStatus { guard (self.status == .notDetermined) else { return self.status } guard (AppStateTracker.shared.state == .active) else { return .notDetermined } locationManager.requestAlwaysAuthorization() await waitActive() return self.status } var status: AirshipPermissionStatus { switch(locationManager.authorizationStatus) { case .notDetermined: return .notDetermined case .restricted: return .denied case .denied: return .denied case .authorizedAlways: return .granted case .authorizedWhenInUse: return .granted @unknown default: return .notDetermined } } } @MainActor private func waitActive() async { var subscription: AnyCancellable? await withCheckedContinuation { continuation in subscription = NotificationCenter.default.publisher(for: AppStateTracker.didBecomeActiveNotification) .first() .sink { _ in continuation.resume() } } subscription?.cancel() } ``` #### Objective-C ```objc #import #import @interface LocationPermissionDelegate : NSObject @property (nonatomic, strong) CLLocationManager *locationManager; @end @implementation LocationPermissionDelegate - (instancetype)init { self = [super init]; if (self) { _locationManager = [[CLLocationManager alloc] init]; } return self; } - (UAPermissionStatus)checkPermissionStatus { return [self status]; } - (void)requestPermissionWithCompletionHandler:(void (^)(UAPermissionStatus))completionHandler { if ([self status] != UAPermissionStatusNotDetermined) { completionHandler([self status]); return; } if ([UAAppStateTracker shared].state != UAAppStateActive) { completionHandler(UAPermissionStatusNotDetermined); return; } [self.locationManager requestAlwaysAuthorization]; // Wait for app to become active and check status dispatch_async(dispatch_get_main_queue(), ^{ completionHandler([self status]); }); } - (UAPermissionStatus)status { switch (self.locationManager.authorizationStatus) { case kCLAuthorizationStatusNotDetermined: return UAPermissionStatusNotDetermined; case kCLAuthorizationStatusRestricted: case kCLAuthorizationStatusDenied: return UAPermissionStatusDenied; case kCLAuthorizationStatusAuthorizedAlways: case kCLAuthorizationStatusAuthorizedWhenInUse: return UAPermissionStatusGranted; default: return UAPermissionStatusNotDetermined; } } @end ``` ### Register the Permission Delegate After creating a location `PermissionDelegate`, register it with `PermissionsManager` [after takeOff](https://www.airship.com/docs/developer/sdk-integration/apple/installation/getting-started/#calling-takeoff): #### Swift ```swift Airship.permissionsManager.setDelegate( LocationPermissionDelegate(), permission: .location ) ``` #### Objective-C ```objc LocationPermissionDelegate *delegate = [[LocationPermissionDelegate alloc] init]; [[UAirship permissionsManager] setDelegate:delegate permission:UAPermissionLocation]; ```