# @microsoft/react-native-clarity

A React Native plugin that allows integrating Clarity with your application.

## Notes

- React Native versions earlier than `0.64` are not supported.
- **Platform Support**: Android and iOS.
- iOS support was experimental before version `4.0.1` and required enabling the `enableIOS_experimental` feature flag.
- The Clarity package depends on native code to run. Therefore, you've to ship a new build after integrating the package.
- Expo Go does not support plugins requiring native code to execute. Hence, Clarity SDK  doesn't operate if you're running through Expo GO. To run the SDK locally, use the [EAS Build](https://docs.expo.dev/build/setup/) system.

## Installation

### Step 1: Add package dependency

To add the package, run the following command.

```bash
npm install @microsoft/react-native-clarity
```

#### [iOS Only] Install native dependencies

```bash
cd ios && pod install
```

### Step 2: Initialize Clarity

Initialize Clarity by adding the following.

```typescript
import * as Clarity from '@microsoft/react-native-clarity';

Clarity.initialize('<project-id>', {
  /* logLevel: Clarity.LogLevel.Verbose, */
});
```

### Step 3: Testing

After integrating Clarity with your application, ensure these steps for testing on a device or a simulator:

1. Your device or simulator should be connected to the internet.
2. The OS version on your device or simulator should be within the supported range specified at [Platform/Framework Support Matrix](https://learn.microsoft.com/en-us/clarity/mobile-sdk/react-native-sdk#platformframework-support-matrix).
3. For initial setup, consider setting the log level to Verbose. This provides detailed logs that can help identify any initialization issues.

Allow approximately 2 hours for complete sessions to appear in your Clarity project on the Clarity website. However, in-progress sessions can still be viewed in real time. See [Clarity Recordings in Real Time](https://learn.microsoft.com/en-us/clarity/session-recordings/clarity-real-time).

## Known issues

- **For `react-native-svg` Users**: A known issue in `react-native-svg` version 13.x affects user interaction and playback when used with Clarity. Upgrade to `react-native-svg` version 14 or later for proper behavior and compatibility.

## Usage

```js
import * as Clarity from '@microsoft/react-native-clarity';

// Initialize Clarity.
const clarityConfig = {
  logLevel: Clarity.LogLevel.Verbose
};

Clarity.initialize('<project-id>', clarityConfig);

// Pauses the Clarity session capturing until a call to the 'resume' function is made.
Clarity.pause();

// Resumes the Clarity session capturing only if it was previously paused by a call to the `pause` function.
Clarity.resume();

// Checks if Clarity session capturing is currently paused based on an earlier call to the `pause` function.
Clarity.isPaused().then((paused) => {...});

// Forces Clarity to start a new session asynchronously.
Clarity.startNewSession(sessionId => {
  // Sets a custom user ID for the current session. This ID can be used to filter sessions on the Clarity dashboard.
  Clarity.setCustomUserId("<CustomUserId>");

  // Sets a custom session ID for the current session. This ID can be used to filter sessions on the Clarity dashboard.
  Clarity.setCustomSessionId("<CustomSessionId>");

  // Sets a custom tag for the current session. This tag can be used to filter sessions on the Clarity dashboard.
  Clarity.setCustomTag("key", "value");
});

// Sends a custom event to the current Clarity session. These custom events can be used to track specific user interactions or actions that Clarity's built-in event tracking doesn't capture.
Clarity.sendCustomEvent('Initialized');

// Sets a callback function that's invoked whenever a new Clarity session starts or an existing session is resumed at app startup.
// If the callback is set after a session has already started, the callback is invoked right away with the current session ID.
Clarity.setOnSessionStartedCallback(sessionId => { });

// Provide a custom screen name tag that's added as a suffix to the base screen name.
Clarity.setCurrentScreenName('Home');

// [DEPRECATED] This function is deprecated and will be removed in a future major version.
// Returns the ID of the currently active Clarity session if a session has already started; otherwise `null`.
Clarity.getCurrentSessionId().then((id) => {...});

// Returns the URL of the current Clarity session recording on the Clarity dashboard if a session has already started; otherwise `null`.
Clarity.getCurrentSessionUrl().then((url) => {...});

// Sets the user's consent status for data collection.
Clarity.consent(true, true);
```

### Using Clarity With React Navigation

```js
import * as Clarity from '@microsoft/react-native-clarity';
import { NavigationContainer useNavigationContainerRef } from '@react-navigation/native';

const HomeScreen = ({...}) => {
  const navigationRef = useNavigationContainerRef();
  const routeNameRef = React.useRef();

  return (
    <NavigationContainer
      ref={navigationRef}
      onReady={() => {
        routeNameRef.current = navigationRef.getCurrentRoute().name;
        const clarityConfig = {
          logLevel: Clarity.LogLevel.Verbose
        };

        Clarity.initialize('<project-id>', clarityConfig);
        Clarity.setCurrentScreenName(routeNameRef.current);
      }}
      onStateChange={() => {
        const previousRouteName = routeNameRef.current;
        const currentRouteName = navigationRef.getCurrentRoute().name;

        if (previousRouteName !== currentRouteName) {
          routeNameRef.current = currentRouteName;
          Clarity.setCurrentScreenName(currentRouteName);
        }
      }}
    >
      {/* ... */}
    </NavigationContainer>
  );
};
```

### Initialization arguments

```ts
/**
 * @param projectId - The unique identifier assigned to your Clarity project. You can find it on the **Settings** page of Clarity dashboard. This ID is essential for routing data to the correct Clarity project (required).
 * @param config - Configuration of Clarity that tunes the SDK behavior (e.g., what user ID to use, log level, ...etc) (optional).
 *
 * **Notes:**
 * - The initialization function is asynchronous, meaning it returns before Clarity is fully initialized.
 * - For actions that require Clarity to be fully initialized, it's recommended to use the {@linkcode setOnSessionStartedCallback} function.
 */
function initialize(projectId: string, config?: ClarityConfig)

/**
 * A class that allows you to configure the Clarity SDK behavior.
 */
export interface ClarityConfig {
  /**
   * @deprecated This property is deprecated and will be removed in a future major version. Please use {@linkcode setCustomSessionId} instead.
   *
   * The unique identifier associated with the application user. This ID persists across multiple sessions on the same device.
   *
   * **Notes:**
   * - If no {@linkcode userId} is provided, a random one will be generated automatically.
   * - Must be a base-36 string smaller than `1Z141Z4`.
   * - If an invalid {@linkcode userId} is supplied:
   *     - If no `customUserId` is specified, {@linkcode userId} will be used as a `customUserId`, and a new random {@linkcode userId} will be assigned.
   *     - If `customUserId` is specified, the invalid {@linkcode userID} will be ignored.
   * - For more flexibility in user identification, consider using the {@linkcode setCustomUserId} API. However, keep in mind that `customUserId` length must be between 1 and 255 characters.
   */
  userId?: string;

  /**
   * The level of logging to show in the device’s logging stream while debugging. By default, the SDK logs nothing.
   */
  logLevel?: LogLevel;
}
```

## License

MIT
