npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-acoustic-connect

v19.0.11

Published

React native plugin for Acoustic Connect

Readme

react-native-acoustic-connect

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.

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)
  • react-native-nitro-modules at the exact version this package pins in peerDependencies (currently 0.35.9) — your app must resolve exactly this version; see Nitro version pin
  • 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 SDK 55+ is supported via the bundled Expo Config Plugin — development builds only (Expo Go is not supported); see Using with Expo SDK 55+.

Nitro version pin

This package pins react-native-nitro-modules to an exact version (currently 0.35.9) in its peerDependencies — deliberately not a range. Your app must resolve exactly that version.

Why (important): Nitro patch releases can contain breaking changes. The SDK ships native bindings generated against one specific Nitro version, and Nitro's generated-code ↔ runtime contract is not patch-safe. For example, a 0.35.40.35.9 patch bump changed Nitro's native registration and caused this SDK's HybridObject to fail to load with a ClassNotFoundException, taking the entire module offline at runtime. Because even a patch can break it, a version range (^/~/>=…<…) cannot guarantee compatibility — so the pin is exact.

If your app resolves a different Nitro version, the SDK may fail to start. You can force past the peer check with --legacy-peer-deps / --force, but then you own making it work — we cannot guard against breaking changes in arbitrary future Nitro patch releases. When this SDK adopts a newer Nitro, it ships in a new SDK release with the pin bumped; upgrade the SDK and Nitro together.

Installation

npm install react-native-acoustic-connect 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:

{
  "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 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. |

What npm install / pod install do for you

Both commands run bootstrap steps against your project, not just the package's own build:

  • npm install triggers a postinstall step that (idempotently, best-effort):
    • scaffolds a starter ConnectConfig.json at your project root if one isn't already there,
    • adds the Android permissions Connect needs (INTERNET, ACCESS_NETWORK_STATE, ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION) to android/app/src/main/AndroidManifest.xml,
    • wires android/app/build.gradle to apply the SDK's config.gradle.
  • pod install merges your ConnectConfig.json into the iOS pod's generated config bundle at install time (see the podspec).

None of this touches files outside your project's android//ios/ directories, and re-running either command is safe. After install, run npx acoustic-connect doctor to validate the result — see Setup CLI below.

Setup CLI (acoustic-connect)

The package ships a small CLI, installed as acoustic-connect (invoke it with npx acoustic-connect <command>), that validates and scaffolds the native side of an integration. Both commands auto-detect bare RN vs. Expo and are idempotent — safe to re-run, and they never overwrite a file that's already there.

npx acoustic-connect doctor [dir] [--require-push]

Checks the things that otherwise fail late and confusingly at build time:

  • Node version.
  • ConnectConfig.json values — AppKey, PostMessageUrl / KillSwitchUrl (must be real https URLs, not the placeholder host), iOSAppGroupIdentifier format, iOSDevelopmentTeam format.
  • Android identifiers — the package/namespace is a Java-safe name, and it has a matching client in google-services.json (Expo also checks for a stale android/ from an incremental expo prebuild after an android.package change).
  • iOS entitlements — bare projects need aps-environment + an App Group entitlement (from setup-ios-push, below, or hand-authored).
  • (macOS only) whether a local Apple Development signing identity is installed, when push is on.

The push-related checks above are hard failures only when Connect.PushEnabled is true (or --require-push is passed) — a non-push integration only needs AppKey. doctor exits non-zero on any failure, so it's usable as a CI gate (npx acoustic-connect doctor --require-push).

dir defaults to the current directory. If ConnectConfig.json is missing, doctor scaffolds it first (from a project-local ConnectConfig.example.json if you have one, else from the copy bundled with the package) before running the checks above — so it's also a fine first command to run in a fresh project.

npx acoustic-connect setup-ios-push [dir]

Bare-workflow only — the Expo Config Plugin does the equivalent automatically on expo prebuild. Scaffolds the two iOS push extensions:

  • ConnectNSE (Notification Service Extension — rich-media attachments, delivery tracking)
  • ConnectNCE (Notification Content Extension — expanded rich-media UI)

It writes each extension's Swift source, Info.plist, and entitlements from the SDK's templates (substituting your App Group), adds the App Group + aps-environment entitlement to the host app if it doesn't have one yet, and wires both targets into your .xcodeproj via a bundled Ruby script — which needs ruby and the xcodeproj gem (gem install xcodeproj; ships with CocoaPods, so most Mac dev setups already have it).

Requires macOS and Connect.iOSAppGroupIdentifier already set in ConnectConfig.json — run doctor first if it's missing.

Using with Expo SDK 55+

Expo SDK 55 and newer is supported via the bundled Expo Config Plugin. Development builds only — Expo Go is not supported: Nitro Modules and native push registration require native code that Expo Go cannot load. There is no runtime Expo Go detection or fallback; use expo-dev-client or EAS Build.

Install

npx create-expo-app@latest my-app    # Expo SDK 55+, new architecture enabled
cd my-app
npx expo install expo-dev-client expo-build-properties
npm install react-native-acoustic-connect react-native-nitro-modules

expo-build-properties is needed to raise Android minSdkVersion to 26 (the Connect Android SDK floor — Expo templates default to a lower value):

{
  "expo": {
    "plugins": [
      ["expo-build-properties", { "android": { "minSdkVersion": 26 } }]
    ]
  }
}

Configure

  1. Put ConnectConfig.json at the project root — the same file documented in Installation. For push, set PushEnabled, iOSPushMode, iOSAppGroupIdentifier, and iOSDevelopmentTeam (your 10-char Apple Team ID) in the Connect block. Run npx acoustic-connect doctor to validate it — when PushEnabled is true, the doctor fails (exits non-zero) on any missing push input (collector URLs, App Group, signing team, google-services.json, app ids); when push is off it needs only AppKey.

  2. Add the plugin to app.json:

{
  "expo": {
    "plugins": ["react-native-acoustic-connect"]
  }
}

The plugin reads the App Group from Connect.iOSAppGroupIdentifier and the signing team from Connect.iOSDevelopmentTeam in ConnectConfig.json — the same values the SDK reads at runtime, so the entitlement and the runtime config agree by construction. To override either for the native project only (rarely needed), pass plugin props; props take precedence over ConnectConfig.json:

{
  "expo": {
    "plugins": [
      [
        "react-native-acoustic-connect",
        {
          "iosAppGroupIdentifier": "group.com.example.myapp",
          "iosDevelopmentTeam": "ABCDE12345"
        }
      ]
    ]
  }
}

iosDevelopmentTeam is required for push: during expo prebuild the plugin stamps DEVELOPMENT_TEAM onto the host app and both push extensions. Without a team, a CLI build falls back to ad-hoc signing, which drops the aps-environment entitlement — so iOS issues no APNs token and push silently fails.

Build

npx expo prebuild
npx expo run:ios -- --extra-params "-allowProvisioningUpdates"   # or: eas build --profile development --platform ios
npx expo run:android    # or: eas build --profile development --platform android

iOS push needs provisioning. Setting iOSDevelopmentTeam lets the plugin stamp the team, but xcodebuild still has to fetch/create the Development certificate and provisioning profiles (the host + both extension App IDs, with the Push Notifications and App Groups capabilities). Pass -allowProvisioningUpdates so it does that automatically — it requires your Apple ID to be added once in Xcode → Settings → Accounts. eas build manages the whole signing chain itself, so no flag is needed there; CI/headless runs can use an App Store Connect API key (-authenticationKeyPath/-authenticationKeyID/-authenticationKeyIssuerID with -allowProvisioningUpdates). For the bare workflow, the equivalent is react-native run-ios --extra-params "-allowProvisioningUpdates".

During expo prebuild the plugin automatically:

  • adds a ConnectNSE Notification Service Extension target to the Xcode project (rich-media push attachments + delivery tracking), with NotificationService.swift generated from the SDK template;
  • adds a ConnectNCE Notification Content Extension target (rich expansion UI — renders the attached media / expanded body when the user expands an Acoustic notification), with NotificationViewController.swift generated from the SDK template;
  • adds the App Group entitlement to the host app and to both extensions, so all three processes share the same pending store;
  • appends ConnectNSE and ConnectNCE targets to the generated Podfile, each linking the same Connect SDK pod as the app.

Re-running expo prebuild — with or without --clean — is idempotent: no duplicate targets, entitlements, or Podfile entries.

The NCE renders notifications whose category matches ACOUSTIC_RICH_NOTIFICATION or ACTIONABLE_NOTIFICATION (the categories the Connect backend sets on rich-media pushes). No app-side configuration is required — the category identifiers are baked into the generated target's Info.plist.

EAS Build

The plugin works with EAS Build out of the box — the NSE and NCE targets are provisioned by the same expo prebuild step EAS runs on its build workers. iOS extension targets are signed automatically when you use EAS-managed credentials (eas credentials), which provisions the host app and both extension App IDs together.

eas build --profile development --platform ios
eas build --profile development --platform android

A working example — including a sample eas.json — lives in Examples/expo.

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:

// index.js
import AcousticConnectRN from 'react-native-acoustic-connect'
// 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:

import AcousticConnectRN from 'react-native-acoustic-connect'

// 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.

import { useNavigationContainerRef, NavigationContainer } from '@react-navigation/native'
import { Connect } from 'react-native-acoustic-connect'

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)

import AcousticConnectRN from 'react-native-acoustic-connect'

// 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 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. Required when push is on. | | iOSDevelopmentTeam | string | null | null | 10-char Apple Team ID used to sign the host + push extensions. Required for iOS push — without it the build drops aps-environment and the OS issues no APNs token. | | AndroidNotificationIconResName | string | null | null | Drawable resource name for the Android notification small icon. |

When PushEnabled is true, npx acoustic-connect doctor treats the push-required inputs above (plus collector URLs, google-services.json, and the app ids) as hard failures and exits non-zero. When push is off it validates only AppKey — a non-push integration needs nothing more.

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 for end-to-end recipes.

Migration from earlier versions

See 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

This package pins react-native-nitro-modules to an exact version (see Nitro version pin). If npm install errors on the Nitro peer, your app is resolving a different Nitro version. Check it with:

npm ls react-native-nitro-modules

Supported fix: align your app to the exact version this package requires (and match React Native / React per the Requirements).

--legacy-peer-deps / --force will silence the error, but the pin is intentional: a mismatched Nitro version can break the SDK at runtime (an init-time ClassNotFoundException), and bypassing means you take on that risk — we cannot guard against breaking changes in arbitrary Nitro patch releases. Match the version rather than bypass it.

iOS — push session reaches the collector but no notifications arrive (no APNs token)

Fingerprint: analytics and pushRegistration still reach the collector normally, but mobileToken stays null forever — and, notably, no didFailToRegisterForRemoteNotificationsWithError (or any push-related failure) shows up in logs either. It just silently never happens. That absence of any error is what makes this look like a missing/broken app-side callback or an SDK bug at first glance; it's almost always a signing artifact instead. Run npx acoustic-connect doctor first — it detects this exact condition (missing/invalid iOSDevelopmentTeam, no Development certificate) up front, before you go digging through portal config.

Cause: a CLI build (expo run:ios / react-native run-ios / xcodebuild) doesn't auto-pick a signing team the way the Xcode GUI does. With no team, it signs ad-hoc and drops the aps-environment entitlement, so iOS issues no APNs token — the app still launches and analytics reach the collector, but no pushRegistration with a mobileToken is ever sent.

Setting Connect.iOSDevelopmentTeam in ConnectConfig.json by itself does nothing. It's just a source value — it has no effect on the build until expo prebuild / npx acoustic-connect setup-ios-push actually stamps DEVELOPMENT_TEAM onto the host and the ConnectNSE and ConnectNCE targets in the generated .pbxproj. Re-run that step any time iOSDevelopmentTeam changes, and after every fresh clone — a teammate's machine may already have the stamp baked in from a prior run; yours doesn't until you run it too. This is the classic "works for me, not for them" trap: every portal-side check (App ID push capability, provisioning profile, entitlements file contents, App Group registration, .p8 key upload) can look perfect and still not reflect what's actually embedded in the binary that got installed on the device.

Fix:

  1. Set Connect.iOSDevelopmentTeam (10-char Apple Team ID) in ConnectConfig.json (or pass the iosDevelopmentTeam plugin prop). Re-run expo prebuild / npx acoustic-connect setup-ios-push so the team is stamped on the host + extensions.
  2. Build with -allowProvisioningUpdates (see Build) and your Apple ID added in Xcode → Settings → Accounts, so a Development certificate + profiles are provisioned.

Verify the fix actually landed — rerunning the steps above isn't proof by itself; confirm the build artifacts directly:

# 1. DEVELOPMENT_TEAM must be stamped on the host AND both push extensions
grep DEVELOPMENT_TEAM ios/*.xcodeproj/project.pbxproj

# 2. The *installed* binary must carry the entitlement — check the actual
#    .app, not just the source .entitlements file in your repo
codesign -d --entitlements :- --xml /path/to/YourApp.app
# must show aps-environment in the output

If DEVELOPMENT_TEAM is missing for any of the three targets, or codesign doesn't show aps-environment, the stamp didn't take (or a stale build was reused) — re-run setup-ios-push / prebuild and do a clean rebuild.

iOS — Expo Android build fails: No matching client found for package name …

Your app.json android.package isn't registered in the active google-services.json (FCM matches by package). The config plugin and acoustic-connect doctor now catch this up front. Register that exact package in the same Firebase project and re-download google-services.json — and note that changing android.package requires a clean prebuild (npx expo prebuild --platform android --clean); an incremental prebuild keeps the stale applicationId.

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 and the sample app walk-through.