> ## Documentation Index
> Fetch the complete documentation index at: https://docs.castled.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting Started with React Native SDK

> [!NOTE]
>
> **Prerequisites**
>
> * [Castled CEP account is already setup](https://docs.castled.io/account-management/user-signup.md)

React Native is a JavaScript library for building apps on multiple platforms like Android and iOS, by maintaining a single code base.

**Castled React Native SDK** enables your React Native App to receive push, in-app and inbox notifications originating from the Castled Customer Engagement Platform.
It is implemented as a [**Turbo Native Module**](https://reactnative.dev/docs/next/the-new-architecture/pillars-turbomodules) with backward compatability. Turbo Native Modules
are the next iteration on React Native Modules for apps based on the [New Architecture](https://reactnative.dev/docs/the-new-architecture/landing-page).

> [!NOTE]
>
> If your react app is on legacy architecture, you will still be able to use the
> Castled SDK as Turbo Native Modules are backward compatible.

## Installation

To use the SDK, add the library to your project

```bash npm
  npm install castled-react-native-sdk
```

```bash yarn
  yarn add castled-react-native-sdk
```

## Native Setup

> [tab] Android
>
> #### Step 1.  Update `build.gradle`
>
> Include `google-services` plugin dependency in top-level gradle file
>
> ```gradle android/build.gradle
> // Top-level build file where you can add configuration options common to all sub-projects/modules.
> buildscript {
>     repositories {
>         // Add google maven repository
>         google()
>     }
>     ...
>     dependencies {
>         ...
>         classpath("com.google.gms:google-services:<plugin-version>")
>     }
> }
> ```
>
> Apply `google-services` plugin to app gradle file
>
> ```gradle android/app/build.gradle
>   apply plugin: "com.google.gms.google-services"
>
> ```
>
> #### Step 2. Required permissions
>
> By default `AndroidManifest.xml` of the SDK includes the following permission requests. No developer action is required here.
>
> ```xml
> <!-- Castled SDK needs this permission to sync user token and campaign events  -->
> <uses-permission android:name="android.permission.INTERNET"/>
> <!-- Castled SDK will use this permission to decide when to make network calls -->
> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
> ```

> [tab] iOS
>
> #### Step 1: Pod Installation
>
> Navigate to ios directory of your app project and run `pod install`
>
> > [!WARNING]
> >
> > When integrating a Swift library such as **Castled** into a React Native project, you may encounter an issue during the pod install process.
> > This issue arises because Swift pods, including **Castled**, depend on libraries which do not define modules.
> > In React Native projects, integrating Swift pods as static libraries requires the generation of module maps for proper Swift compatibility.
> >
> > To resolve this issue, follow these steps to configure your Podfile:
> >
> > ```pod
> > target 'YourTargetName' do
> >   config = use_native_modules!
> >
> >   #  Other pods
> >   pod 'SDWebImage', '~> 5.11', :modular_headers => true
> >
> > end
> > ```
> >
> > Save the Podfile and run `pod install` again.
>
> > [!WARNING]
> >
> > When adding a cocoapods dependency for apps on **React Native** version **0.64** or **0.65**, you might get errors like these:
> >
> > ```bash
> > ld: Undefined symbols:
> > clang: error: linker command failed with exit code 1 (use -v to see invocation)
> > ```
> >
> > The issue seemes to be that projects bootstrapped by `react-native init`, has `LIBRARY_SEARCH_PATHS` set to the following:
> >
> > ```bash
> > LIBRARY_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)" "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)" "$(inherited)"
> > ```
> >
> > Simply clearing out `LIBRARY_SEARCH_PATHS` so that it's empty will fix the issue.
> >
> > **Before**
> > ![Before](https://mintlify.s3-us-west-1.amazonaws.com/castled/images/sdk/react-native/ios/before-fix.png)
> >
> > **After**
> > ![After](https://mintlify.s3-us-west-1.amazonaws.com/castled/images/sdk/react-native/ios/after-fix.png)

## Initialization

Next step is to initialize the SDK. Initialization is typically done in `App.js`.

```tsx
  import * as React from 'react';
  // Importing SDK modules required for initialization
  import {
    CastledNotifications,
    CastledConfigs,
    CastledLocation,
  } from 'castled-react-native-sdk';

  export default function App() {

    ...

    React.useEffect(() => {
      // Set config
      const configs = new CastledConfigs();
      configs.appId = '<app-id>';
      configs.location = CastledLocation.US;

      // Initialize SDK
      CastledNotifications.initialize(configs);
    }, []);

    ...

    return (
      <>
        ...
      </>
    );
  }
```

* `app-id` is a unique key associated with your Castled account. It can be found in the Castled dashboard at **Settings > Api Keys**.
* `location` is the region where you have your Castled account.

You can refer to the **SDK Configs** section for the list of configs available during initialization.

### User Identification

To identify the user associated with an app instance, use the following method. This is typically invoked immediately after user completes the
sign-in flow of your app. `user-id` is the id that you use internally within your organisation to identify a user.

```tsx
// User identification
CastledNotifications.setUserId("<user-id>")
```

> [!NOTE]
>
> It is recommended to pass an optional **user-token** as the second parameter
> to `setUserId` to mitigate any risk of user impersonation. In the absence of a
> **user-token**, no additional verifications will be done to enforce user
> authenticity. If your **user-id** is random id such as a UUID, **user-token**
> is probably not required. More info on **user-token** can be found in the next
> section.

### Secure User Identification

`user-token` is a unique token per user generated by your app server. This token is usually issued by the app server as a part of user login flow.

```tsx
// Secure user identification
CastledNotifications.setUserId("<user-id>", "<user-token>")
```

`user-token` is a Base64 encoded **Hash-based Message Authentication Code** (HMAC). Ensure the hash computation happens in your app server so that `api-key`
is not exposed. You can create an `api-key` in the **Setting > API Keys** page within your Castled account. Contact Castled support for help with integration.

Find sample server code snippets to generate **HMAC** for the `user-id`.

```java java
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;

    public static String calculateHMAC(String userId, String apiKey) throws Exception {
        // Get an instance of the HMAC using SHA-256 hashing algorithm
        Mac sha256Hmac = Mac.getInstance("HmacSHA256");

        // Create a SecretKeySpec using the provided key
        SecretKeySpec secretKey = new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");

        // Initialize the Mac with the secret key
        sha256Hmac.init(secretKey);

        // Compute the HMAC of the given data
        byte[] rawHmac = sha256Hmac.doFinal(userId.getBytes(StandardCharsets.UTF_8));

        // Convert the HMAC bytes to a Base64 encoded string
        return Base64.getEncoder().encodeToString(rawHmac);
    }
```

```go go
    import (
        "crypto/hmac"
        "crypto/sha256"
        "encoding/base64"
        "fmt"
    )

    func calculateHMAC(message string, apiKey string) string {
        key := []byte(apiKey)
        h := hmac.New(sha256.New, key)
        h.Write([]byte(message))

        // Encoding the HMAC as a Base64 encoded string
        return base64.StdEncoding.EncodeToString(h.Sum(nil))
    }
```

### User Logout

To remove the user association with a particular app instance. Typically invoked as part of the user sign-out flow within the app. Once invoked, app won't be able to
receive any notifications sent from Castled until the user sign-in to the app again.

```tsx
// User logout
CastledNotifications.logout()
```

## SDK Configs

This section covers the basic configurations available in the `CastledConfigs` class of the SDK.
Use these configs if you want to enable specific messsaging channel or want to override default behavior.

| Config Name | Description | Default Value |
| - | - | - |
| enablePush | Enables push notification feature | false |
| enablePushBoost | Enhances push notification delivery rates on Android devices with the advanced push boost feature | false |
| enableInApp | Enables In App notification feature | false |
| enableAppInbox | Enables App Inbox notification feature | false |
| enableTracking | Enables tracking of User attributes or App events | false |
| enableSessionTracking | Enables tracking of User Sessions | true |
| location | Preferred server location | US |
| skipUrlHandling | Disables the click action handling by the SDK. Set when app handles the notification action itself | false |

> [!NOTE]
>
> Push boost feature has to be included in your account plan for
> `enablePushBoost` to work as expected. For any inquiries or further
> assistance, please contact our support team.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.