Deep linking, attribution, and smart links for React Native.
Part of the Grovs open-source mobile linking platform.
Quick Start · API Reference · Full Docs
The Grovs React Native SDK provides deep linking, universal links, app links, link generation, in-app messaging, revenue tracking, and attribution for your React Native apps.
- Deep linking & universal links: route users to the right in-app screen, even after install
- Clipboard deferred deep linking: match an install to a link the user copied before installing
- Consent support: remember the user’s choice across launches
- Smart link generation: create trackable links with metadata, custom redirects, and UTM parameters
- In-app messaging: messages from the Grovs dashboard, with pause, resume, excluded screens and events
- Push notifications: receive push campaigns, with tap tracking and iOS rich push
- Revenue tracking: log App Store, Google Play, and custom purchases with automatic attribution
- Analytics: automatic lifecycle events, custom events, and screen tracking
- User identity: attach user IDs and attributes for analytics and segmentation
- Self-hosting support: point the SDK at your own backend
- Expo support: config plugin for automated native setup
- React Native 0.70+
- iOS 13.0+
- Android API 21+ (Android 5.0)
These are the minimums of the native Grovs SDKs. Your React Native version may require a higher one.
The wrapper uses these Grovs native SDKs:
- iOS:
Grovs3.1 from CocoaPods - Android:
io.grovs:Grovs:3.1.0from Maven Central
# Using npm
npm install react-native-grovs-wrapper
# Using yarn
yarn add react-native-grovs-wrapperYour app calls Grovs directly from MainApplication and MainActivity, so add the Grovs Android SDK to android/app/build.gradle:
dependencies {
implementation 'io.grovs:Grovs:3.1.0'
}It is published on Maven Central, so no extra repository is needed. The Expo config plugin adds this line for you.
The iOS SDK is added automatically via CocoaPods when you run pod install. After upgrading the wrapper, run pod install again.
CocoaPods trunk no longer accepts new versions, so new Grovs iOS releases are installed from the Grovs GitHub repo. Add this inside your app target in ios/Podfile, with the tag matching grovsIosSdkVersion in the wrapper's package.json:
pod 'Grovs', :git => 'https://github.com/grovs-io/grovs-iOS.git', :tag => '3.1.0'The Expo config plugin adds this line for you.
- Run
pod installagain so iOS picks up the Grovs 3.1 pods. We recommend installing them from git, see iOS dependency. DeeplinkResponse.linkis optional now. A push without a link arrives without it.- The wrapper owns the native in-app delegate (iOS) and listener (Android). Remove any you set yourself and use
onInAppMessage. - On Android the wrapper only fetches the FCM token for you if your manifest opts in. See the Android push setup.
displayMessages()andnumberOfUnreadMessages()do nothing now. They resolve, and the count is always0.
If you're using Expo with a development build, the config plugin automates all native setup. Add to your app.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://your-domain.com",
"clipboardDomains": ["links.your-domain.com"]
}]
]
}| Property | Required | Description |
|---|---|---|
apiKey |
Yes | Your Grovs API key |
scheme |
Yes | Custom URL scheme for deep links |
useTestEnvironment |
No | Use test environment (default: false) |
associatedDomains |
No | Universal link domains for deep linking |
baseURL |
No | Custom base URL for self-hosted backends |
clipboardDomains |
No | Extra link hosts accepted for clipboard deferred deep linking. Grovs hosts are always accepted |
push |
No | Set up push (see below). Default false |
iosRichPush |
No | Create the iOS Notification Service Extension for images in pushes. Needs push. Needs ios.bundleIdentifier |
appleTeamId |
No | Apple team id used to sign the extension. The plugin does not read ios.appleTeamId, so set it here |
androidNotificationIcon |
No | Name of a drawable used as the small notification icon |
Set "push": true to add the native push setup:
- iOS: adds the
aps-environmententitlement (developmentif missing),didRegisterForRemoteNotificationsWithDeviceTokencallingGrovs.setPushToken(deviceToken:), and auserNotificationCenter(_:didReceive:...)method callingGrovs.handleNotificationResponse. That method only runs if your app makesAppDelegatethe notification center delegate. The plugin never sets the delegate. If a push library owns it, usehandleNotificationOpeninstead (see Push notifications) and wire only one path. - Android: adds
firebase-messaging(skipped if@react-native-firebase/messagingis installed),POST_NOTIFICATIONSand theio.grovs.wrapper.FetchFirebaseTokenflag that lets the wrapper fetch the FCM token. If@react-native-firebase/messagingorexpo-notificationsis installed, it removes the GrovsMessagingService. Firebase config comes from Expo'sandroid.googleServicesFile.
"iosRichPush": true creates the GrovsNotificationService extension target with bundle id <app bundle id>.GrovsNotificationService and adds the EAS appExtensions entry.
The plugin installs the Grovs pod, and the GrovsNotificationService pod when iosRichPush is on, from the Grovs GitHub repo at the tag the wrapper is built for. Each prebuild moves them to the current tag.
{
"expo": {
"android": { "googleServicesFile": "./google-services.json" },
"plugins": [
["react-native-grovs-wrapper", {
"apiKey": "your-api-key",
"scheme": "your_app_scheme",
"push": true,
"iosRichPush": true,
"appleTeamId": "ABCDE12345",
"androidNotificationIcon": "ic_notification"
}]
]
}
}The extension's Podfile block follows the stock Expo use_frameworks! setup, including expo-build-properties useFrameworks. If another plugin forces a different linkage, align it. With EAS remote versioning, check that the extension's build number matches the app's.
Tested with Expo SDK 58.
Then run npx expo prebuild and build with npx expo run:ios / npx expo run:android.
When upgrading an existing Expo integration or changing plugin options, regenerate with npx expo prebuild --clean to refresh the configure calls. Save any manual native edits first.
Note: This requires a development build (
expo-dev-client), not Expo Go.
1. Initialize the SDK in your MainApplication class:
import com.grovswrapper.GrovsConsent
import io.grovs.Grovs
override fun onCreate() {
super.onCreate()
Grovs.configure(
this, "your-api-key",
useTestEnvironment = false,
baseURL = null, // or "https://your-domain.com" for self-hosted backends
autoTrackScreenViews = false,
clipboardDomains = null, // or listOf("links.your-domain.com")
enabled = GrovsConsent.isEnabled(this) // the value JS last passed to setSDK, default true
)
}2. Handle incoming links in your MainActivity:
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 to your launcher activity in AndroidManifest.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>1. Initialize the SDK in AppDelegate.swift:
import Grovs
import react_native_grovs_wrapper
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Grovs.configure(
APIKey: "your-api-key",
useTestEnvironment: false,
// baseURL: "https://your-domain.com", // self-hosted backends
autoTrackScreenViews: false,
// clipboardDomains: ["links.your-domain.com"],
enabled: GrovsWrapperSwift.isSDKEnabled(), // the value JS last passed to setSDK, default true
delegate: GrovsWrapperSwift.shared
)
Grovs.setDebug(level: .info)
return true
}2. Handle incoming links in AppDelegate.swift:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
return Grovs.handleAppDelegate(continue: userActivity, restorationHandler: restorationHandler)
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
return Grovs.handleAppDelegate(open: url, options: options)
}3. Configure Associated Domains in Xcode:
- Select your app target → Signing & Capabilities
- Add Associated Domains capability
- Add
applinks:your_app_hostandapplinks:your_app_test_host
4. Configure URL scheme:
- In Xcode, select your target → Info tab
- Under URL Types, click + and add the URL scheme from your Grovs dashboard
import Grovs from 'react-native-grovs-wrapper';
const listener = Grovs.onDeeplinkReceived((response) => {
console.log('Link:', response.link);
console.log('Data:', response.data);
// Route the user based on payload
if (response.data?.screen === 'product') {
navigation.navigate('Product', { id: response.data.productId });
}
});
// When you no longer need the listener
listener.remove();Grovs.setIdentifier('user-123');
Grovs.setAttributes({
name: 'John Doe',
plan: 'premium',
});Call setSDK(false) when the user declines analytics and setSDK(true) when they accept. The wrapper remembers the last value, and the native configure call reads it on the next launch, so a user who declined stays opted out from the first frame of the next cold start.
While disabled, the SDK blocks new authentication, event and purchase requests and cancels work in progress. Identifier, attributes, push token and screen aliases you set are kept and sent once the SDK is enabled again. On Android, a link opened while disabled is delivered as soon as you enable the SDK.
Grovs.setSDK(await consentStore.hasAnalyticsConsent());generateLink, numberOfUnreadMessages and displayMessages reject with code SDK_DISABLED while the SDK is disabled.
If a user copies a Grovs link before installing, the SDK checks the clipboard once on first launch, only when fingerprint matching found nothing, and delivers the match through onDeeplinkReceived. It can arrive several seconds after launch. On iOS the system shows its paste notice the first time. Only links on Grovs hosts and the clipboardDomains you configure are accepted.
Create smart links with metadata, payload data, and tracking parameters:
try {
const link = await Grovs.generateLink({
title: 'Check out this product',
subtitle: 'Limited time offer',
imageURL: 'https://example.com/image.jpg',
data: { productId: '12345', screen: 'product_detail' },
tags: ['promotion', 'share'],
customRedirects: {
android: { link: 'https://example.com/android', open_if_app_installed: true },
ios: { link: 'https://example.com/ios', open_if_app_installed: true },
desktop: { link: 'https://example.com/desktop', open_if_app_installed: false },
},
showPreviewIos: false,
showPreviewAndroid: false,
tracking: { utm_campaign: 'spring_sale', utm_source: 'in_app', utm_medium: 'share_button' },
copyToClipboardIos: true, // landing page copies the link so the install can be matched
copyToClipboardAndroid: true, // leave undefined to inherit the project default
});
console.log('Generated:', link);
} catch (error) {
console.error('Error:', error);
}The older positional form generateLink(title, subtitle, imageURL, data, tags, customRedirects, showPreviewIos, showPreviewAndroid, tracking, copyToClipboardIos, copyToClipboardAndroid) still works.
Leave the copy flags undefined to inherit the project default.
Fetch the details of a link generated in the current environment by its path. The path is the part after the domain, without the leading / and without any query string, for example abc123:
try {
const details = await Grovs.linkDetails('abc123');
console.log(details.title, details.data, details.tags);
} catch (error) {
// The link does not exist, the request failed, or the SDK is disabled (SDK_DISABLED)
console.error('Error:', error);
}The result has the type LinkDetails. It includes fields such as path, title, subtitle, image, data, tags, access_path, active, the tracking fields and the custom redirects.
If console messages have automatic display enabled in your dashboard, they will appear in your app without any additional integration.
Push is opt-in. Upload your APNs key (.p8) and Firebase credentials in the Grovs dashboard. The Expo config plugin can do the native setup for you, see the push options in Expo Integration.
A push with a Grovs link is delivered through onDeeplinkReceived, like any other link. A push without a link still arrives there, without link.
1. Add the capabilities. In Xcode, add Push Notifications and Background Modes (Remote notifications) to your app target. Your app asks for permission and calls registerForRemoteNotifications() itself.
2. Send the token. Either forward it from AppDelegate.swift:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Grovs.setPushToken(deviceToken: deviceToken)
}or, if you use @react-native-firebase/messaging, pass the APNs token from JS:
import messaging from '@react-native-firebase/messaging';
const token = await messaging().getAPNSToken();
if (token) {
Grovs.setPushToken(token);
}3. Handle taps. Wire exactly one of these paths. Wiring both counts every tap twice on iOS.
-
Native path. If
AppDelegateis your notification center delegate, forward the response:func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { Grovs.handleNotificationResponse(response) completionHandler() }
-
JS path. If a push library owns the delegate, call
handleNotificationOpenfrom its tap listeners. It resolvestruewhen the push is a Grovs push. Call it on taps only, never when a push is delivered.// @react-native-firebase/messaging messaging().onNotificationOpenedApp((message) => { Grovs.handleNotificationOpen(message.data ?? {}); }); const initial = await messaging().getInitialNotification(); if (initial) { Grovs.handleNotificationOpen(initial.data ?? {}); } // expo-notifications let lastHandledId: string | undefined; const handleTap = (response: Notifications.NotificationResponse) => { const { request } = response.notification; // On a cold start the same tap can reach both the listener and getLastNotificationResponseAsync. if (request.identifier === lastHandledId) { return; } lastHandledId = request.identifier; // Stops the tap from being replayed after a JS reload. Skip this if other code in your app reads the last response. Notifications.clearLastNotificationResponseAsync(); // On iOS, content.data only holds the "body" key of an APNs push; the full payload is in the trigger. Grovs.handleNotificationOpen((request.trigger as any)?.payload ?? request.content.data); }; Notifications.addNotificationResponseReceivedListener(handleTap); const last = await Notifications.getLastNotificationResponseAsync(); if (last) { handleTap(last); }
isGrovsNotification(data) resolves true if the payload came from Grovs, without handling it.
4. Rich push (optional). To show images in pushes, add a Notification Service Extension target in Xcode (File > New > Target > Notification Service Extension). Then add it to your Podfile:
target 'GrovsNotificationService' do
pod 'GrovsNotificationService', :git => 'https://github.com/grovs-io/grovs-iOS.git', :tag => '3.1.0'
endand make the extension class a subclass:
import GrovsNotificationService
class NotificationService: GrovsNotificationServiceExtension {}Run pod install again after this.
1. Add Firebase. Add your google-services.json, the Google Services Gradle plugin and the Firebase Messaging dependency to your app. For Android 13+, declare the permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />Your app asks the user for this permission at runtime.
2. Token. The wrapper can fetch the FCM token for you at each cold start. This is off by default. To turn it on, add this inside <application> in AndroidManifest.xml (the Expo plugin does it when push is true):
<meta-data android:name="io.grovs.wrapper.FetchFirebaseToken" android:value="true" />It needs firebase-messaging in your app. The token is not sent while the SDK is disabled with setSDK(false), and it is fetched again when you call setSDK(true). While the Grovs MessagingService is in place, it also picks up new tokens. If you removed that service (see "Using another push library" below), pass new tokens yourself, for example with @react-native-firebase/messaging:
const token = await messaging().getToken();
if (token) {
Grovs.setPushToken(token);
}
messaging().onTokenRefresh((newToken) => Grovs.setPushToken(newToken));3. Taps. Taps on pushes Android shows for you are handled from the launcher intent, through the Grovs.onStart and Grovs.onNewIntent calls you already have in MainActivity. If a push library shows pushes while the app is open (for example expo-notifications), their taps do not reach the launcher intent. Call handleNotificationOpen from its tap listeners, as in the iOS JS path. A tap the launcher intent already handled is not handled a second time.
4. Notification icon (optional). Set a small icon in AndroidManifest.xml, inside <application>:
<meta-data android:name="io.grovs.NotificationIconSmall" android:resource="@drawable/ic_notification" />Using another push library. Only one service can receive Firebase messages. If your app uses @react-native-firebase/messaging or expo-notifications, remove the Grovs service so that library keeps working. Add xmlns:tools="http://schemas.android.com/tools" to <manifest>, then inside <application>:
<service android:name="io.grovs.handlers.MessagingService" tools:node="remove" />Taps and background pushes still work. What you lose is Grovs drawing pushes while the app is open; your push library handles that. Forward taps on those pushes with handleNotificationOpen (see 3. Taps above).
Your own messaging service. If your app has its own FirebaseMessagingService, remove the Grovs service as above and forward to Grovs:
import io.grovs.GrovsMessaging
override fun onMessageReceived(message: RemoteMessage) {
GrovsMessaging.handleMessage(this, message)
}
override fun onNewToken(token: String) {
GrovsMessaging.onNewToken(token)
}In-app messages created in the dashboard are shown by the native SDK. From JS you can control them and listen to what happens:
// Hold messages back, for example during onboarding
Grovs.pauseInAppMessages();
Grovs.resumeInAppMessages();
// Drop queued messages. Pass dismissCurrent to close the one on screen too
Grovs.discardInAppMessages({ dismissCurrent: true });
// Never show messages on these screens (names as sent to trackScreenView)
Grovs.setInAppExcludedScreens(['Checkout', 'Onboarding']);
Grovs.setInAppDebugLogging(true);
const subscription = Grovs.onInAppMessage((event) => {
if (event.type === 'clicked') {
console.log(event.campaignId, event.buttonId, event.payload);
}
});
subscription.remove();Excluded screens match the names you send through trackScreenView or startScreenTracking, after aliases are applied.
onInAppMessage events:
type |
Fields | When |
|---|---|---|
shown |
campaignId |
A message appeared |
clicked |
campaignId, buttonId?, payload? |
The user tapped a button |
dismissed |
campaignId, reason |
The message was closed. reason is close_button, backdrop, swipe, app or orientation. Other values may be added later |
answered |
campaignId, value, comment? |
The user answered a question. value is the stars (number) or the option id (string) |
failed |
message, campaignId? |
The message could not be shown |
Events that happen before your first onInAppMessage call (for example a message shown on app open) are kept, up to 20, and delivered when you subscribe.
The wrapper owns Grovs.inAppDelegate (iOS) and Grovs.setInAppListener (Android). Do not set them in native code, or onInAppMessage stops receiving events.
There is no way to veto a message from JS. Use pause, resume, discard and excluded screens instead.
Test messages from the dashboard need setIdentifier to be set.
On Android you can optionally add the Google Play review dependency so review prompts can be shown:
implementation 'com.google.android.play:review-ktx:2.0.2'The push permission button in an in-app message on Android needs POST_NOTIFICATIONS declared in your manifest.
The message inbox is deprecated and does nothing in native 3.1. The methods still resolve, and numberOfUnreadMessages() resolves 0.
await Grovs.displayMessages();
const count = await Grovs.numberOfUnreadMessages();Revenue tracking is currently in beta.
- Enable revenue tracking in the Grovs dashboard under Settings → Revenue Tracking
- Configure platform notifications:
- Android: Set up Google Play Real-Time Developer Notifications
- iOS: Configure App Store Server Notifications in App Store Connect
// iOS: StoreKit 2 transaction id
const success = await Grovs.logInAppPurchase({ transactionId: '123456789' });
// Android: Play Billing purchase original JSON
const success = await Grovs.logInAppPurchase({
originalJson: purchase.originalJson,
});The SDK automatically extracts price, currency, and product info. Duplicates are filtered.
const success = await Grovs.logCustomPurchase(
'buy', // type: 'buy' | 'cancel' | 'refund'
999, // priceInCents: $9.99
'USD', // currency code
'premium_monthly', // product identifier
);Use 'cancel' and 'refund' types for cancellations and refunds. For store purchases, these are detected automatically via platform server notifications.
The native SDKs automatically capture lifecycle events: install, reinstall, app_open, reactivation, and time_spent. No setup required.
Grovs.track('purchase', { item_id: 'sku-42', price: 19.99 }, ['promo']);Event names must not be empty or use a reserved system name (view, open, install, reinstall, app_open, time_spent, reactivation, user_referred, custom, screen_view). Properties are dropped if they serialize to more than 8KB, and tags are capped at 20 (255 characters each).
Attach tags to every subsequently tracked event:
Grovs.setGlobalTags(['beta']);
// Clear global tags
Grovs.setGlobalTags();With React Navigation, one line enables automatic screen view tracking:
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import Grovs from 'react-native-grovs-wrapper';
function App() {
const navigationRef = useNavigationContainerRef();
return (
<NavigationContainer
ref={navigationRef}
onReady={() => Grovs.startScreenTracking(navigationRef)}>
{/* navigators */}
</NavigationContainer>
);
}startScreenTracking returns an unsubscribe function, and calling it again replaces the previous subscription: screens are never double-tracked. Consecutive duplicate screen views within 1 second are deduplicated natively.
For Expo Router or custom navigators, track screens manually:
Grovs.trackScreenView('Checkout', { section: 'payment' });Map screen names to friendly names shown in the Grovs dashboard:
Grovs.setScreenAliases({ Home: 'Home Page' });The native SDKs' own automatic screen tracking only sees the single React Native host Activity/ViewController, so it should be disabled in React Native apps:
- Expo: the config plugin disables it automatically. If you're upgrading the plugin, re-run
npx expo prebuild --clean. - Manual / bare React Native: pass
autoTrackScreenViews: falsein the native configure calls:
// iOS
Grovs.configure(APIKey: "...", useTestEnvironment: false, autoTrackScreenViews: false, enabled: GrovsWrapperSwift.isSDKEnabled(), delegate: GrovsWrapperSwift.shared)// Android
Grovs.configure(this, "API_KEY", useTestEnvironment = false, baseURL = null, autoTrackScreenViews = false, clipboardDomains = null, enabled = GrovsConsent.isEnabled(this))| Method | Description |
|---|---|
onDeeplinkReceived(callback) |
Register deep link listener (returns { remove }) |
setSDK(enabled) |
Enable or disable the SDK. Remembered across launches |
setDebug(level) |
Set logging level ('info', 'error') |
setPushToken(token) |
Set FCM/APNs push token |
handleNotificationOpen(data) |
Handle a push tap from your push library. Resolves true for a Grovs push. On Android it skips taps the launcher intent already handled |
isGrovsNotification(data) |
Resolves true if the payload is from Grovs |
pauseInAppMessages() / resumeInAppMessages() |
Hold back or release in-app messages |
discardInAppMessages(opts?) |
Drop queued in-app messages. { dismissCurrent: true } also closes the one on screen |
setInAppExcludedScreens(screens) |
Do not show in-app messages on these screens |
setInAppDebugLogging(enabled) |
Log in-app message activity |
onInAppMessage(callback) |
Listen to in-app events (returns { remove }) |
setIdentifier(identifier) |
Set user ID for dashboard and reports |
setAttributes(attributes) |
Set user attributes for analytics |
generateLink(options) |
Generate a smart link (GenerateLinkOptions; positional form still supported). Rejects with SDK_DISABLED while disabled |
linkDetails(path) |
Get the details of a link by its path. Rejects if the link does not exist, the request fails, or the SDK is disabled (SDK_DISABLED) |
displayMessages() |
Deprecated. Resolves without showing anything. Rejects with SDK_DISABLED while disabled |
numberOfUnreadMessages() |
Deprecated. Resolves 0. Rejects with SDK_DISABLED while disabled |
logInAppPurchase(purchase) |
Log a store purchase ({ transactionId } on iOS, { originalJson } on Android) |
logCustomPurchase(type, priceInCents, currency, productId, startDate?) |
Log a custom purchase |
track(name, properties, tags) |
Track a custom analytics event |
trackScreenView(screenName, properties) |
Track a screen view |
setGlobalTags(tags) |
Attach tags to every subsequent event (call with no args to clear) |
setScreenAliases(aliases) |
Map screen names to friendly dashboard names |
startScreenTracking(navigationRef) |
Auto-track React Navigation screen changes (returns unsubscribe) |
Full API reference: docs.grovs.io/docs/sdk/react-native/api-reference
This repository has two example apps that use the local wrapper:
example/: the new architecture (TurboModules)example_old_arch/: the legacy bridge
See CONTRIBUTING.md for how to run them. A standalone demo project is also available at grovs-io/grovs-react-native-example-app.
Full documentation at docs.grovs.io.
For technical support and inquiries, contact support@grovs.io.
This project is licensed under the MIT License: see LICENSE for details.