# Quick start

> Install and configure the Grovs React Native SDK in your app.

Source: https://docs.grovs.io/docs/sdk/react-native/quick-start

Install the wrapper, wire the native side and open your first link on a device. Takes about fifteen minutes, less with Expo.

**Using an AI coding agent?**

Copy one prompt into Claude Code, Cursor or Copilot and it does these steps in your project.

```text
Add Grovs deep linking to this React Native app (example app: Medly).

1. Install react-native-grovs-wrapper.
2. Expo with a development build: add the react-native-grovs-wrapper config plugin to app.json (apiKey, scheme, useTestEnvironment, associatedDomains) and run npx expo prebuild --clean, then skip to step 5.
3. Android: add implementation 'io.grovs:Grovs:3.1.0' to android/app/build.gradle. Call Grovs.configure in MainApplication with autoTrackScreenViews = false and enabled = GrovsConsent.isEnabled(this). Forward onStart and onNewIntent in MainActivity. Add the intent filters.
4. iOS: call Grovs.configure in AppDelegate.swift with autoTrackScreenViews: false, enabled: GrovsWrapperSwift.isSDKEnabled() and delegate: GrovsWrapperSwift.shared. Forward incoming links, add the URL scheme and Associated Domains, then run pod install.
5. Read the API key from the existing secrets setup (env GROVS_API_KEY). Use the test environment only in debug builds.
6. Register Grovs.onDeeplinkReceived early in the app and route response.data to the existing navigation.
7. Build both platforms, then list what you changed.

Docs: https://docs.grovs.io/docs/sdk/react-native/quick-start.md
```

> **Note:** This page covers wrapper 3.1.0, which wraps iOS SDK 3.1 and Android SDK 3.1.0. Upgrading from 3.0.x? See the [upgrade guide](https://docs.grovs.io/docs/upgrade-guides/react-native-3-1). From 1.x, see the [3.0 upgrade guide](https://docs.grovs.io/docs/upgrade-guides/react-native-3-0).

## Requirements

- React Native 0.70+, new architecture (TurboModules) or legacy bridge
- iOS 13.0+ and Android 5.0 (API 21)+, the native SDK minimums. Your React Native version may need more.
- A Swift `AppDelegate` and Kotlin `MainApplication` / `MainActivity`, as current React Native and Expo templates generate. The snippets and the Expo plugin assume them.

## Installation

```bash
# Using npm
npm install react-native-grovs-wrapper

# Using yarn
yarn add react-native-grovs-wrapper
```

### Android dependency

`MainApplication` and `MainActivity` call `Grovs` directly, so the app needs its own Android SDK dependency, at the version the wrapper is built against. Add it to `android/app/build.gradle`:

```groovy
dependencies {
    implementation 'io.grovs:Grovs:3.1.0'
}
```

Wrapper 3.0.2 uses `3.0.1`, and 3.0.0 and 3.0.1 use `3.0.0`.

It's on Maven Central, so no extra repository is needed. The Expo config plugin adds this line for you.

### iOS dependency

The wrapper's podspec depends on `Grovs ~> 3.1` (`~> 3.0` in wrapper 3.0.x), so `pod install` in `ios/` adds the iOS SDK. Run `pod install` again after upgrading the wrapper.

## Expo integration

With an Expo development build (`expo-dev-client`, not Expo Go), the config plugin automates the native setup below. Add it to `app.json`:

```json
{
  "plugins": [
    ["react-native-grovs-wrapper", {
      "apiKey": "your-api-key",
      "scheme": "your_app_scheme",
      "useTestEnvironment": false,
      "associatedDomains": ["your_app_host", "your_app_test_host"],
      "baseURL": "https://sdk.example.com",
      "clipboardDomains": ["links.yourdomain.com"]
    }]
  ]
}
```

| Property                  | Required | Default | Description                                                                                                                                                                                                                              |
| ------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`                  | Yes      |         | Your Grovs API key                                                                                                                                                                                                                       |
| `scheme`                  | Yes      |         | Custom URL scheme for deep links, from the Grovs dashboard                                                                                                                                                                               |
| `useTestEnvironment`      | No       | `false` | Use your project's test environment                                                                                                                                                                                                      |
| `associatedDomains`       | No       | `[]`    | Universal link and App Link hosts. Sent to iOS as `applinks:` entries, adding the prefix if missing                                                                                                                                      |
| `baseURL`                 | No       | none    | Base URL of a [self-hosted backend](https://docs.grovs.io/docs/self-hosting/configure/sdk-configuration)                                                                                                                                 |
| `clipboardDomains`        | No       | `[]`    | Extra link hosts accepted by [clipboard-assisted deferred deep linking](https://docs.grovs.io/docs/sdk/react-native/deep-linking#clipboard-assisted-deferred-deep-linking). Must be an array of strings; Grovs hosts are always accepted |
| `push`                    | No       | `false` | Adds the native [push setup](https://docs.grovs.io/docs/sdk/react-native/push-notifications#with-expo)                                                                                                                                   |
| `iosRichPush`             | No       | `false` | Creates the iOS Notification Service Extension for [campaign images](https://docs.grovs.io/docs/sdk/react-native/push-notifications#campaign-images-ios). Needs `push` and `ios.bundleIdentifier`                                        |
| `appleTeamId`             | No       | none    | Apple team that signs the extension. `ios.appleTeamId` isn't read                                                                                                                                                                        |
| `androidNotificationIcon` | No       | none    | Drawable name for the Android small notification icon                                                                                                                                                                                    |

The push options need wrapper 3.1.0.

The plugin adds:

- the URL scheme and Associated Domains to the iOS project
- the intent filters to `AndroidManifest.xml`
- the `io.grovs:Grovs` dependency to `android/app/build.gradle`
- the `configure` and link-forwarding code to `AppDelegate.swift`, `MainApplication.kt` and `MainActivity.kt`

The injected `configure` calls pass `autoTrackScreenViews: false`, so the native SDKs don't report the React Native host as a screen. They pass `enabled: GrovsWrapperSwift.isSDKEnabled()` / `enabled = GrovsConsent.isEnabled(this)`, so a `setSDK` consent choice survives a cold start. Objective-C or Java app files fail with an error.

Run `npx expo prebuild`, then build with `npx expo run:ios` / `npx expo run:android`. The plugin is tested with Expo SDK 58.

> **Warning:** The plugin skips any file that already contains `Grovs.configure`. After upgrading the wrapper or changing plugin options, run `npx expo prebuild --clean` to regenerate the `configure` calls. Save manual native edits first.

## Android configuration

### 1. Initialize the SDK

In your `MainApplication` class:

```kotlin
import io.grovs.Grovs
import com.grovswrapper.GrovsConsent

override fun onCreate() {
    super.onCreate()
    Grovs.configure(
        this,
        "your-api-key",
        useTestEnvironment = false,
        baseURL = null,                          // or "https://sdk.example.com" for a self-hosted backend
        autoTrackScreenViews = false,            // the native tracker only sees the React Native host Activity
        clipboardDomains = null,                 // or listOf("links.yourdomain.com")
        enabled = GrovsConsent.isEnabled(this)   // the value JavaScript last passed to setSDK, true by default
    )
}
```

Android `configure` has no defaults after `baseURL`, so pass every parameter. Keep `autoTrackScreenViews = false`: native tracking can't see individual React Native screens. Track them from JavaScript with [`startScreenTracking`](https://docs.grovs.io/docs/sdk/react-native/analytics#automatic-screen-tracking-with-react-navigation). `GrovsConsent.isEnabled` reads the value stored by `setSDK` (see [Privacy & Consent](https://docs.grovs.io/docs/sdk/react-native/privacy)). Parameters: [Android Quick Start](https://docs.grovs.io/docs/sdk/android/quick-start#configuration-options).

### 2. Handle incoming links

In your `MainActivity` class:

```kotlin
import android.content.Intent
import io.grovs.Grovs

override fun onStart() {
    super.onStart()
    Grovs.onStart(launcherActivity = this)
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    Grovs.onNewIntent(intent, launcherActivity = this)
}
```

### 3. Add intent filters

Add these to your launcher activity in `AndroidManifest.xml`:

```xml
<!-- Custom URL scheme -->
<intent-filter>
    <data android:scheme="your_app_scheme" android:host="open" />
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

<!-- App links (production) -->
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="your_app_host" />
</intent-filter>

<!-- App links (test) -->
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="your_app_test_host" />
</intent-filter>
```

## iOS configuration

### 1. Initialize the SDK

In your `AppDelegate.swift`:

```swift
import Grovs
import react_native_grovs_wrapper

override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    Grovs.configure(
        APIKey: "your-api-key",
        useTestEnvironment: false,
        // baseURL: "https://sdk.example.com",        // self-hosted backend
        autoTrackScreenViews: false,                   // the native tracker only sees the React Native host view controller
        clipboardDomains: nil,                         // or ["links.yourdomain.com"]
        enabled: GrovsWrapperSwift.isSDKEnabled(),     // the value JavaScript last passed to setSDK, true by default
        delegate: GrovsWrapperSwift.shared             // the wrapper delivers links to JavaScript
    )
    // Optional: verbose logging while integrating
    Grovs.setDebug(level: .info)

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
```

Keep the `super` call and return its result; `RCTAppDelegate` bootstraps React Native there.

Pass `GrovsWrapperSwift.shared` as the delegate, as the Expo plugin does. `nil` also works: the wrapper sets itself as the delegate once launch finishes. Don't pass your own `GrovsDelegate`; the wrapper replaces it. `GrovsWrapperSwift.isSDKEnabled()` reads the value stored by `setSDK` (see [Privacy & Consent](https://docs.grovs.io/docs/sdk/react-native/privacy)). Parameters: [iOS Quick Start](https://docs.grovs.io/docs/sdk/ios/quick-start#configuration-options).

### 2. Handle incoming links

Add to your `AppDelegate.swift`:

```swift
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    return Grovs.handleAppDelegate(continue: userActivity, restorationHandler: restorationHandler)
}

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    return Grovs.handleAppDelegate(open: url, options: options)
}
```

If your `AppDelegate` already implements one (to chain `RCTLinkingManager`, say), call `Grovs.handleAppDelegate` first inside it and return `true` when it handled the link.

### 3. Configure Associated Domains

1. Open the iOS project in Xcode.
2. Select your app target → **Signing & Capabilities**.
3. Add the **Associated Domains** capability.
4. Add `applinks:your_app_host` and `applinks:your_app_test_host`.

### 4. Configure URL scheme

1. In Xcode, select your target → **Info** tab.
2. Under **URL Types**, click **+**.
3. Add the production and test URL schemes from your Grovs dashboard.

## Basic usage

```typescript
import Grovs from 'react-native-grovs-wrapper';

// Optional: identify the user
Grovs.setIdentifier('user_id_from_your_app');
Grovs.setAttributes({ name: 'John Doe', plan: 'premium' });

// Receive deep links
const listener = Grovs.onDeeplinkReceived((response) => {
    console.log('Link:', response.link, 'Data:', response.data);
});
```

## Next steps

- [Handle incoming deep links →](https://docs.grovs.io/docs/sdk/react-native/deep-linking)
- [Generate smart links →](https://docs.grovs.io/docs/sdk/react-native/link-creation)
- [Receive push campaigns →](https://docs.grovs.io/docs/sdk/react-native/push-notifications)
- [React to in-app messages →](https://docs.grovs.io/docs/sdk/react-native/in-app-messages)
- [Track events and screens →](https://docs.grovs.io/docs/sdk/react-native/analytics)
- [Gate collection on user consent →](https://docs.grovs.io/docs/sdk/react-native/privacy)
- [Explore the React Native example app →](https://github.com/grovs-io/grovs-react-native-example-app)

## See also

- [Integrating an npm package](https://docs.grovs.io/docs/how-to-guides/react-native/npm): install the wrapper with npm
- [Integrating a Yarn Package](https://docs.grovs.io/docs/how-to-guides/react-native/yarn): install with yarn
- [How to Add an Associated Domain](https://docs.grovs.io/docs/how-to-guides/ios/associated-domain): Xcode steps in detail
- [How to Add a New Intent Filter](https://docs.grovs.io/docs/how-to-guides/android/intent-filter): Android intent filters in detail
- [Deep link not opening the app](https://docs.grovs.io/docs/troubleshooting/deep-link-not-opening-app): links open the browser instead of the app
- [SDK configuration issues](https://docs.grovs.io/docs/troubleshooting/sdk-configuration-issues): common setup and initialization problems
