---
title: Collecting device profiles in iOS
description: PingOne Advanced Identity Cloud PingAM iOS
component: orchsdks
page_id: orchsdks:journey:use-cases/device-profiling/ios-device-profile
canonical_url: https://developer.pingidentity.com/orchsdks/journey/use-cases/device-profiling/ios-device-profile.html
revdate: Tue, 29 Oct 2025 14:22:33 +0100
keywords: ["Device", "Hardware", "Source Code", "Integration", "SDK", "iOS"]
section_ids:
  ios_device-profile_module: Step 1. Installing modules
  iOS_device-profile_permissions: Step 2. Declaring permissions
  step_3_collecting_device_profiles: Step 3. Collecting device profiles
  integrating_with_swiftui: Integrating with SwiftUI
  creating_custom_collectors: Creating custom collectors
  integrating_with_advanced_identity_cloud_and_pingam_journeys: Integrating with Advanced Identity Cloud and PingAM journeys
---

# Collecting device profiles in iOS

[icon: circle-check, set=far]PingOne Advanced Identity Cloud [icon: circle-check, set=far]PingAM [icon: apple, set=fab]iOS

The Device Profile module helps you to collect various attributes from an iOS device.

It includes preconfigured collectors to collect attributes, and allows you to create your own collectors to suit your requirements.

## Step 1. Installing modules

To install the Device Profile module for iOS, use Swift Package Manager (SPM) or Cocoapods to add the dependency to your project.

* SPM (Swift Package Manager)

* CocoaPods

You can install packages by using SPM (Swift Package Manager) on the iOS project.

1. In Xcode, in the Project Navigator, right-click your project, and then click Add Package Dependencies…​.

2. In the **Search or Enter Package URL** field, enter the URL of the repo containing the Orchestration SDK for iOS, `https://github.com/ForgeRock/ping-ios-sdk.git`.

3. In **Add to Project**, select the name of your project, and then click **Add Package**.

   Xcode shows a dialog containing the libraries available for iOS.

4. Select the `PingDeviceProfile` library, and in the **Add to Target** column select the name of your project.

5. Repeat the previous step for any other packages you want to use in your project.

6. Click **Add Package**.

   Xcode displays the chosen packages and any prerequisites they might have in the **Package Dependencies** pane of the Project Navigator.

1) If you don't already have CocoaPods, install the [latest version](https://guides.cocoapods.org/using/getting-started.html).

2) If you don't already have a Podfile, in a terminal window, run the following command to create a new [Podfile](https://guides.cocoapods.org/syntax/podfile.html):

   ```
   pod init
   ```

3) Add the following lines to your Podfile:

   ```
   pod 'PingDeviceProfile'
   ```

4) Run the following command to install pods:

   ```
   pod install
   ```

## Step 2. Declaring permissions

The Device Profile module respects the iOS permissions model, and certain collectors require that you declare the permissions needed.

To declare the permissions the app might request from the user:

1. Right-click the project's `info.plist` file, and select **Open As** > **Source Code**.

   Xcode displays the contents of the plist file as XML, ready for editing.

2. Add the following properties as a child of the top-level `<dict>` element:

   ```xml
   <key>NSLocationWhenInUseUsageDescription</key>
   <string>This app needs location access to enhance security and provide personalized experiences.</string>
   <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
   <string>This app needs location access to enhance security and provide personalized experiences.</string>
   <key>NSBluetoothAlwaysUsageDescription</key>
   <string>This app uses BLE to collect device information</string>
   ```

   |   |                                                                                                           |
   | - | --------------------------------------------------------------------------------------------------------- |
   |   | The `LocationCollector` automatically requests the relevant permission when gathering the data if needed. |

3. Save your changes.

## Step 3. Collecting device profiles

To create a device profile, create a list of the collectors you want to use, or specify `DefaultDeviceCollector.defaultDeviceCollectors()` to use the default list, and then call the `collect()` method to create the device profile JSON:

Obtaining a device profile on an iOS device

```swift
import DeviceProfile

func collectDeviceProfile() async {
    // Initialize collectors with default set
    let collectors = DefaultDeviceCollector.defaultDeviceCollectors()

    // Or manually select specific collectors
    let customCollectors: [any DeviceCollector] = [
        PlatformCollector(),
        HardwareCollector(),
        NetworkCollector(),
        TelephonyCollector(),
        BrowserCollector(),
        BluetoothCollector()
        // LocationCollector() // Add separately if needed
    ]

    do {
        // Collect device information
        let deviceProfile = try await collectors.collect()

        // Use the collected profile (Dictionary)
        print("Device Profile: \(deviceProfile)")
    } catch {
        print("Collection failed: \(error)")
    }
}
```

The **device-profile** module provides the following collectors:

**Included device profile collectors**

| Collector            | Attributes collected                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PlatformCollector`  | Gathers platform and device identification information, such as the brand and model.Example data returned by the `PlatformCollector````json
{
   "platform": {
      "platform": "iOS",
      "version": "17.0.1",
      "device": "iPhone",
      "deviceName": "Babs' iPhone",
      "model": "iPhone15,2",
      "brand": "Apple",
      "locale": "en",
      "timeZone": "America/New_York",
      "jailBreakScore": 0.0
   }
}
```                                                        |
| `HardwareCollector`  | Gathers information about the hardware, such as the CPU and display.Example data returned by the `HardwareCollector````json
{
   "hardware": {
      "manufacturer": "Apple",
      "memory": 6144,
      "cpu": 6,
      "display": {
         "width": 393,
         "height": 852,
         "orientation": 1
      },
      "camera": {
         "numberOfCameras": 3
      }
   }
}
```                                                                                                     |
| `NetworkCollector`   | Whether the device has any network connectivity.Example data returned by the `NetworkCollector````json
{
   "network": {
      "connected": true
   }
}
```                                                                                                                                                                                                                                                                                                                                     |
| `TelephonyCollector` | Collects information about the carriers the device uses, such as the carrier name and the country code.Example data returned by the `TelephonyCollector````json
{
   "telephony": {
      "networkCountryIso": "US",
      "carrierName": "Verizon"
   }
}
```                                                                                                                                                                                                                                  |
| `LocationCollector`  | Collects latitude and longitude coordinates from the device.- Automatically requests permissions when needed

- Handles both "when in use" and "always" authorization types

- Gracefully handles permission denials

- Includes intelligent caching, with 5-second validity

- Returns `null` if a location is unavailable or permission is deniedExample data returned by the `LocationCollector````json
{
   "location": {
      "latitude": 37.2431,
      "longitude": 115.7930
   }
}
``` |
| `BluetoothCollector` | Whether the device has any bluetooth support.Example data returned by the `BluetoothCollector````json
{
    "bluetooth": {
        "supported": true
    }
}
```                                                                                                                                                                                                                                                                                                                                |
| `BrowserCollector`   | Collects the user-agent string of the default browser on the device.Example data returned by the `BrowserCollector````json
{
   "browser": {
      "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15..."
   }
}
```                                                                                                                                                                                                                                     |

### Integrating with SwiftUI

The following example demonstrates how to integrate collection of a device profile with SwiftUI:

Integrating profile collection with SwiftUI

```swift
import SwiftUI
import DeviceProfile

struct ContentView: View {
    @State private var deviceProfile: [String: Any] = [:]
    @State private var isCollecting = false

    var body: some View {
        VStack {
            if isCollecting {
                ProgressView("Collecting device information…​")
            } else {
                Button("Collect Device Profile") {
                    Task {
                        await collectProfile()
                    }
                }
            }
        }
    }

    private func collectProfile() async {
        isCollecting = true
        defer { isCollecting = false }

        let collectors = DefaultDeviceCollector.defaultDeviceCollectors()

        do {
            deviceProfile = try await collectors.collect()
        } catch {
            print("Collection error: \(error)")
        }
    }
}
```

## Creating custom collectors

You can create custom device collectors to gather specific attributes, depending on your requirements or the hardware you will support.

Use the `DeviceCollector` protocol to create your custom collector:

Using `DeviceCollector` protocol to create a custom collector

```swift
struct BatteryCollector: DeviceCollector {
    typealias DataType = BatteryInfo

    let key = "battery"

    func collect() async throws -> BatteryInfo? {
        return BatteryInfo(
            level: UIDevice.current.batteryLevel,
            state: UIDevice.current.batteryState.rawValue
        )
    }
}

struct BatteryInfo: Codable {
    let level: Float
    let state: Int
}
```

## Integrating with Advanced Identity Cloud and PingAM journeys

You can use the Device Profile module to collect the data the [**Device Profile Collector node**](https://docs.pingidentity.com/auth-node-ref/latest/device-profile-collector.html) requires when used as part of a Advanced Identity Cloud or PingAM auth journey.

The Device Profile module provides the `DeviceProfileCallback` class. The class includes a `collect()` method, which collects the data and formats it ready for return to the server.

Preparing a device profile for the Device Profile Collector node

```swift
let result = await deviceProfileCallback.collect { config in
    // Configure custom collectors for enhanced AIC risk assessment
    config.collectors {
        return [
            PlatformCollector(),
            HardwareCollector(),
            NetworkCollector(),
            BrowserCollector(),
            BluetoothCollector(),
            SecurityCollector() // Custom collector
        ]
    }
}

// Handle the result
result
    .onSuccess { profile in
        // Device profile collected, submit to AIC service
        print("Profile collected successfully")
        node.next()
    }
    .onFailure { error in
        print("Collection failed: \(error)")
    }
```

The module formats the resulting device profile for consumption by the Device Profile Collector node, and includes a device identifier:

Example device profile for the Device Profile Collector node

```json
{
  "identifier": "unique-device-id",
  "metadata": {
    "platform": {
      "platform": "iOS",
      "version": "17.0.1",
      "device": "iPhone"
    },
    "hardware": {
      "manufacturer": "Apple",
      "memory": 6144,
      "cpu": 6
    },
    "network": {
      "connected": true
    }
  },
  "location": {
    "latitude": 37.2431,
    "longitude": 115.7930
  }
}
```

The **Device Profile** module automatically uses the **Device ID** module to generate this identifier, but you can customize how it's generated:

Customizing the device identifier on iOS

```swift
import PingDeviceId

// Define custom device identifier config:
let identifierConfig = DeviceIdentifierConfiguration(
    keychainAccount: "com.mycompany.myapp.deviceid",
    useEncryption: true,
    keySize: 2048
)

let customDeviceIdentifier = try? DefaultDeviceIdentifier(configuration: identifierConfig)

let result = await deviceProfileCallback.collect { @Sendable config in
  // Use custom identifier in the device profile
  config.deviceIdentifier = customDeviceIdentifier
}

// Handle the result
result
  .onSuccess { profile in
      // Device profile collected, submit to server
      print("Profile collected successfully")
      node.next()
  }
  .onFailure { error in
      print("Collection failed: \(error)")
  }
```

Learn more about customizing the device identifier in [Customizing device identifiers on iOS](ios-device-ids.html).
