react-native-acoustic-connect-beta
Version:
BETA: React native plugin for Acoustic Connect
264 lines (198 loc) • 10.8 kB
Markdown
# react-native-acoustic-connect-beta
React Native plugin for the Acoustic Connect SDK. Captures user interactions,
screen replays, and analytics events on iOS and Android. Supports optional push
notifications via the Connect backend.
For the full product overview see the
[Connect SDK overview on the developer portal](https://developer.goacoustic.com/acoustic-connect/docs/connect-sdk-overview).
## Requirements
- React Native 0.82.x – 0.85.x with the new architecture
- React 19.1.1 or newer (or whatever your RN version pins)
- Node 20 or newer
- iOS deployment target ≥ 15.1, AcousticConnect / AcousticConnectDebug pod ≥ 2.0.5
- Android `minSdk` ≥ 26, `compileSdk` ≥ 35, `io.github.go-acoustic:connect` in `[11.0.11, 12.0.0)`
- **Expo is not supported by this package.** Expo apps should use the sibling
Config Plugin (tracked separately under PES-4002 / CA-137701).
## Installation
```bash
npm install react-native-acoustic-connect-beta react-native-nitro-modules
cd ios && pod install
```
The plugin reads a `ConnectConfig.json` from your project root at install time
(iOS via the podspec, Android via `config.gradle`) and bakes the values into the
native bundles. **`ConnectConfig.json` is the single source of truth** — there
is no runtime override path. A minimal config looks like:
```json
{
"Connect": {
"AppKey": "your-app-key",
"PostMessageUrl": "https://collector.example.com/collectorPost",
"KillSwitchUrl": "https://collector.example.com/collector/switch/your-app-key",
"useRelease": false,
"PushEnabled": false,
"iOSPushMode": "automatic",
"iOSAppGroupIdentifier": null,
"AndroidNotificationIconResName": null
}
}
```
Field summary (see [API reference](#api-reference) for full semantics):
| Field | Default | Purpose |
| --- | --- | --- |
| `AppKey` | _(required)_ | Your Connect application key. |
| `PostMessageUrl` | _(required)_ | Collector endpoint URL. |
| `KillSwitchUrl` | _(optional)_ | Kill-switch endpoint URL. |
| `useRelease` | `false` | `true` selects the release AcousticConnect iOS pod over the debug variant. |
| `iOSVersion` | `""` | Pin a specific iOS pod version; empty = newest in the supported range. |
| `AndroidVersion` | `""` | Pin a specific Android Connect SDK version; empty = newest in the supported range. |
| `PushEnabled` | `false` | Master switch. On Android, also gates the `connect-push-fcm` artifact inclusion. |
| `iOSPushMode` | `"automatic"` | iOS-only: `"automatic"` (SDK owns APNs delegate) or `"manual"` (app owns it). Ignored when `PushEnabled` is `false`. |
| `iOSAppGroupIdentifier` | `null` | iOS App Group shared with the Notification Service / Notification Content extension. |
| `AndroidNotificationIconResName` | `null` | Drawable resource name (no extension) for the Android notification small icon. |
## Quick start
### 1. Initialise the SDK
The SDK **auto-initialises** at module load time using the values from
`ConnectConfig.json`. For most apps there is no JS-side init code to write —
just import the package and you're done:
```ts
// index.js
import AcousticConnectRN from 'react-native-acoustic-connect-beta'
// SDK is already initialising on the main actor / main looper. No further
// setup required.
```
For consent-gated apps (GDPR, CCPA, COPPA), use the lifecycle pair:
```ts
import AcousticConnectRN from 'react-native-acoustic-connect-beta'
// At app start, if you don't yet have user consent:
AcousticConnectRN.disable()
// Later, after the user opts in:
AcousticConnectRN.enable()
```
`enable()` and `disable()` are both parameterless — all configuration comes
from `ConnectConfig.json`. They're idempotent at the native layer; calling
`enable()` on an already-running SDK is a no-op.
### 2. Add the `<Connect>` wrapper (declarative, in your tree)
Wrap your `NavigationContainer` in `<Connect>` to enable navigation tracking,
touch capture, and optional keyboard / dialog interception. The wrapper does
not own SDK lifecycle — that's been done in step 1 — so it can mount, unmount,
or remount freely without disrupting the session.
```tsx
import { useNavigationContainerRef, NavigationContainer } from '@react-navigation/native'
import { Connect } from 'react-native-acoustic-connect-beta'
export default function App() {
const navigationRef = useNavigationContainerRef()
return (
<Connect
navigationRef={navigationRef}
captureKeyboardEvents
captureDialogEvents
>
<NavigationContainer ref={navigationRef}>
{/* your screens */}
</NavigationContainer>
</Connect>
)
}
```
`<Connect>` is optional. Apps that only need custom event logging (no automatic
screen / touch / keyboard tracking) can skip it entirely.
### 3. Log events (imperative, anywhere)
```ts
import AcousticConnectRN from 'react-native-acoustic-connect-beta'
// Custom application event
AcousticConnectRN.logCustomEvent('checkout_started', { cartId: 'abc' }, 1)
// Force a logical screen name (e.g. for non-NavigationContainer screens)
AcousticConnectRN.setCurrentScreenName('CheckoutScreen')
// Manual exception capture
AcousticConnectRN.logExceptionEvent(
'Payment failed',
err.stack ?? '',
/* unhandled */ false
)
```
Dialog tracking helpers (`useDialogTracking`, `DialogListener`,
`withAcousticAutoDialog`) instrument React Native `Alert.alert(...)` and custom
dialogs automatically. See the
[developer portal](https://developer.goacoustic.com/acoustic-connect/docs/react-native-integration)
for details.
## API reference
### `AcousticConnectRN.enable(): boolean`
Re-enables the SDK after a prior `disable()`. Reads all configuration from
`ConnectConfig.json`. Returns `true` on accepted dispatch; `false` only when
the platform can't satisfy a precondition (e.g. Android without an
`Application` context yet). Idempotent — the native SDK short-circuits if it's
already running.
> The SDK also auto-initialises at module load using the same configuration,
> so you typically don't need to call `enable()` at all. The method exists to
> pair with `disable()` for opt-out / consent flows.
### `AcousticConnectRN.disable(): boolean`
Stops data capture, flushes pending messages, releases push state. Idempotent.
### Push configuration (`ConnectConfig.json`)
| Field | Type | Default | Semantics |
| --- | --- | --- | --- |
| `PushEnabled` | boolean | `false` | Cross-platform master switch. On Android, drives `connect-push-fcm` artifact inclusion at build time. |
| `iOSPushMode` | `"automatic"` / `"manual"` | `"automatic"` | iOS-only. Ignored when `PushEnabled` is `false`. |
| `iOSAppGroupIdentifier` | string \| null | `null` | iOS App Group shared with NSE / NCE for rich push payloads. |
| `AndroidNotificationIconResName` | string \| null | `null` | Drawable resource name for the Android notification small icon. |
#### iOS push modes
- `"automatic"` — the iOS Connect SDK manages APNs token registration internally. The host app only requests user permission via `UNUserNotificationCenter`; token delivery and forwarding to the Connect backend are handled by the SDK.
- `"manual"` — the host app owns APNs delegate callbacks (`application(_:didRegisterForRemoteNotificationsWithDeviceToken:)`) and forwards tokens explicitly via `ConnectSDK.shared.push.didRegisterWithToken(token)`.
#### Android push
The `iOSPushMode` field is iOS-only; Android push is gated solely by
`PushEnabled`. On Android, FCM requires a `FirebaseMessagingService` subclass
that the host app declares in its `AndroidManifest.xml`, so push is always
app-driven. The host app is responsible for:
- shipping `google-services.json` in `android/app/`,
- implementing `FirebaseMessagingService.onNewToken(...)`,
- forwarding the FCM token to the Connect SDK.
The Android push-forwarding API itself is wired under follow-up work — until
that lands, `PushEnabled: true` on Android only changes which artifact is on
the classpath; the host-side token forwarding API is not yet exposed.
### `<Connect>` props
| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | yes | Your `NavigationContainer` (or any subtree). |
| `navigationRef` | `RefObject` | recommended | Ref from `useNavigationContainerRef()`. Enables screen-name tracking. |
| `captureKeyboardEvents` | `boolean` | yes | Capture iOS/Android keyboard show/hide events. |
| `captureDialogEvents` | `boolean` | no (default `false`) | Auto-track `Alert.alert(...)` calls. |
### Other methods
The plugin exposes the full Connect SDK surface — custom events, signals,
exceptions, location, screen layout, click / text-change events, dialog events,
and config-item getters/setters. Signatures are stable across platforms; see
`src/specs/react-native-acoustic-connect.nitro.ts` for the typed Nitro spec and
the
[developer portal](https://developer.goacoustic.com/acoustic-connect/docs/react-native-integration)
for end-to-end recipes.
## Migration from earlier versions
See [Migration-Guide.md](./Migration-Guide.md) for the steps to move from the
legacy `NativeModules.AcousticConnectRN` interface to the current ESM exports
and the `<Connect>` component.
## Troubleshooting
### `npm install` peer-dependency conflicts
If `npm install` errors out on a peer-dependency resolution involving Expo or
older `react-native-nitro-modules` versions, retry with:
```bash
npm install react-native-nitro-modules --legacy-peer-deps
```
This usually only happens when an existing project pulls in stale Expo
transitives. Permanent fix: align RN, React, and Nitro versions with the
[Requirements](#requirements) section above.
### iOS — `pod install` fails with `[Connect] requires AcousticConnect >= 2.0.5`
You've pinned an older `iOSVersion` in `ConnectConfig.json`. Bump it to a
2.0.5+ release (or leave it empty for the newest available) and re-run
`pod install`.
### Android — Gradle resolution fails on `io.github.go-acoustic:connect`
The strict constraint at `[11.0.11, 12.0.0)` is rejecting your pin. Bump
`AndroidVersion` in `ConnectConfig.json` to a release within that range (or
leave it empty for the newest 11.x available). 12.x is intentionally outside
the supported range pending compatibility validation — track that work
separately if you need it.
### Gradle can't find `node`
Common when Gradle is launched outside an NVM-loaded shell. Either:
- Stop the daemon (`./gradlew --stop`) and re-run `npm run android` from a
shell where `which node` resolves, or
- Symlink node onto a stable PATH: `ln -sf "$(which node)" /opt/homebrew/bin/node`.
---
For more, see the
[Connect React Native integration guide](https://developer.goacoustic.com/acoustic-connect/docs/react-native-integration)
and the
[sample app walk-through](https://developer.goacoustic.com/acoustic-connect/docs/build-a-sample-react-native-app).