---
title: Collecting device profiles in React Native apps
description: Collect device profile data in React Native apps using rn-device-profile and integrate with PingOne Advanced Identity Cloud and PingAM journeys
component: orchsdks
page_id: orchsdks:journey:use-cases/device-profiling/react-native-device-profile
canonical_url: https://developer.pingidentity.com/orchsdks/journey/use-cases/device-profiling/react-native-device-profile.html
llms_txt: https://developer.pingidentity.com/orchsdks/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: Tue, 29 Oct 2025 14:22:33 +0100
keywords: ["Device", "Hardware", "Source Code", "Integration", "SDK", "React Native"]
section_ids:
  step_1_installing_the_module: Step 1. Installing the module
  native_module_setup: Native module setup
  step_2_declaring_permissions: Step 2. Declaring permissions
  ios: iOS
  android: Android
  step_3_collecting_device_profiles: Step 3. Collecting device profiles
  available_collectors: Available collectors
  recommended_collector_sets: Recommended collector sets
  step_4_integrating_with_advanced_identity_cloud_and_pingam_journeys: Step 4. Integrating with Advanced Identity Cloud and PingAM journeys
  the_journey_profile_payload: The journey profile payload
---

# Collecting device profiles in React Native apps

[icon: circle-check, set=far]PingOne Advanced Identity Cloud [icon: circle-check, set=far]PingAM [icon: react, set=fab]React Native

This page guides you through collecting device profile data in a React Native application using `@ping-identity/rn-device-profile`.

It includes preconfigured collectors to collect attributes, and allows you to select which collectors to use to suit your requirements.

## Step 1. Installing the module

To install the module into your React Native project, use `yarn` or `npm` as follows:

* yarn

* npm

```shell
yarn add @ping-identity/rn-device-profile
```

```shell
npm install @ping-identity/rn-device-profile
```

For Journey-integrated collection, also install the Journey module if you have not already done so:

* yarn

* npm

```shell
yarn add @ping-identity/rn-journey
```

```shell
npm install @ping-identity/rn-journey
```

After installation, import the functions you need:

Importing device profile functions

```typescript
import {
  collectDeviceProfile,
  collectDeviceProfileForJourney,
} from '@ping-identity/rn-device-profile';
import type { DeviceProfileCollector } from '@ping-identity/rn-device-profile';
```

### Native module setup

`@ping-identity/rn-device-profile` is a TurboModule package. On React Native 0.80.1+ with the new architecture enabled, linking is automatic. On older projects using the legacy bridge, run:

```shell
npx pod-install     # iOS
```

No additional `android/` configuration is required.

## Step 2. Declaring permissions

Some collectors require platform permissions. Add the necessary declarations to your project before enabling those collectors.

### iOS

Open `ios/<AppName>/Info.plist` as source code and add the following entries as children of the top-level `<dict>` element:

Adding iOS permission entries to Info.plist

```xml
<!-- Required for LocationCollector -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to enhance security and provide personalised experiences.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access to enhance security and provide personalised experiences.</string>

<!-- Required for BluetoothCollector -->
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to collect device information.</string>
```

### Android

Open `android/app/src/main/AndroidManifest.xml` and add the following `<uses-permission>` entries inside `<manifest>`:

Adding Android permission entries to AndroidManifest.xml

```xml
<!-- Required for LocationCollector -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- Required for BluetoothCollector (Android 12+) -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

<!-- For Android 11 and earlier -->
<uses-permission android:name="android.permission.BLUETOOTH" />
```

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | For `LocationCollector` and `BluetoothCollector`, you must also request the runtime permission in JavaScript before calling the collector. The SDK does not request permissions automatically on Android. Use React Native's `PermissionsAndroid` API or a library such as `react-native-permissions` to request them at an appropriate point in your UX flow\.On iOS, `LocationCollector` requests the permission automatically when the data is first gathered. |

## Step 3. Collecting device profiles

Call `collectDeviceProfile()` with an array of collector names to gather device attributes:

Collecting a device profile with selected collectors

```typescript
import { collectDeviceProfile } from '@ping-identity/rn-device-profile';
import { logger } from '@ping-identity/rn-logger';

const profileLogger = logger({ level: 'debug' });

const profile = await collectDeviceProfile(
['platform', 'hardware', 'network'],
// Add optional logger
{ logger: profileLogger },
);

// Output collected profile JSON
console.log(JSON.stringify(profile, null, 2));
```

The function returns a plain JavaScript object containing the merged output of all requested collectors. Collectors that fail are omitted from the result without throwing an error.

### Available collectors

| Collector value | Collector output                                                                                                                                                                                                                                                                  |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'platform'`    | ```json
{
  "platform": {
    "platform": "iOS",
    "version": "17.0.1",
    "device": "iPhone",
    "deviceName": "Jane's iPhone",
    "model": "iPhone15,2",
    "brand": "Apple",
    "locale": "en",
    "timeZone": "America/New_York",
    "jailBreakScore": 0.0
  }
}
``` |
| `'hardware'`    | ```json
{
  "hardware": {
    "manufacturer": "Apple",
    "memory": 6144,
    "cpu": 6,
    "display": {
      "width": 393,
      "height": 852,
      "orientation": 1
    },
    "camera": {
      "numberOfCameras": 3
    }
  }
}
```                                       |
| `'network'`     | ```json
{
  "network": {
    "connected": true
  }
}
```                                                                                                                                                                                                                          |
| `'telephony'`   | ```json
{
  "telephony": {
    "networkCountryIso": "US",
    "carrierName": "Verizon"
  }
}
```                                                                                                                                                                                  |
| `'browser'`     | ```json
{
  "browser": {
    "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15..."
  }
}
```                                                                                                                                              |
| `'bluetooth'`   | ```json
{
  "bluetooth": {
    "supported": true
  }
}
```                                                                                                                                                                                                                        |
| `'location'`    | ```json
{
  "location": {
    "latitude": 37.2431,
    "longitude": 115.7930
  }
}
```                                                                                                                                                                                            |

### Recommended collector sets

For most applications, `platform`, `hardware`, and `network` provide a solid baseline signal without requiring any runtime permissions:

```typescript
const profile = await collectDeviceProfile(['platform', 'hardware', 'network']);
```

## Step 4. Integrating with Advanced Identity Cloud and PingAM journeys

When a journey reaches a **Device Profile Collector** node, the SDK receives a `DeviceProfileCallback`.

Call `collectDeviceProfileForJourney()` to collect the device signals and write them into the active journey callback, then call `actions.next()` to advance the node. `DeviceProfileJourneyResult` is an imported type that represents the resolved value from a device profile collection step inside a journey:

Handling a DeviceProfileCallback in a journey node

```typescript
import { collectDeviceProfileForJourney } from '@ping-identity/rn-device-profile';
import { collectDeviceProfileForJourney } from '@ping-identity/rn-device-profile';
import type { DeviceProfileJourneyResult } from '@ping-identity/rn-device-profile';
import { useJourney, useJourneyForm } from '@ping-identity/rn-journey';
import type { JourneyClient } from '@ping-identity/rn-journey';

function useDeviceProfileNode(journeyClient: JourneyClient) {
  const [node, actions] = useJourney(journeyClient);
  const form = useJourneyForm(node);

  const submit = async (): Promise<void> => {
    const hasDeviceProfile = form.fields.some(
      (f) => f.ref.type === 'DeviceProfileCallback',
    );

    if (!hasDeviceProfile) return;

    const result: DeviceProfileJourneyResult =
      await collectDeviceProfileForJourney(journeyClient, [
        'platform',
        'hardware',
        'network',
      ]);

    if (result.type === 'success') {
      await actions.next();
    }
  };
```

|   |                                                                                                                                                                                            |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | Call `collectDeviceProfileForJourney` once per node. It inspects the active node from the journey client automatically. You do not need to pass individual callback references or indexes. |

### The journey profile payload

The profile written to the journey callback includes a device identifier generated by the native platform, the collector output, and any location data. The server-side Device Profile Collector node uses the `identifier` field to correlate the submission with a known device:

Example journey profile payload

```json
{
  "identifier": "a3f8d2...",
  "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
  }
}
```

For details on how the device identifier is generated and how to customize it, see [Customizing device identifiers in React Native apps](react-native-device-ids.html).
