Mobile and native apps
How the widget behaves on mobile browsers, what works in WebViews and Capacitor-style native shells, and what doesn't (yet).
On this page
The Voicegram widget runs in any modern mobile browser without any extra setup. It also runs inside the most common types of hybrid and WebView-based native apps, with one platform caveat about microphone permissions. Pure-native apps (Swift, Kotlin, etc.) are not supported today.
Mobile browsers
The widget works in mobile Chrome, mobile Safari, mobile Firefox, and Samsung Internet without any special configuration. The bubble and modal are responsive and mobile-first by default: touch targets are at least 44 by 44 pixels, the modal renders as a bottom sheet on small screens, and the recorder uses the device microphone.
Minimum versions for reliable recording:
- iOS Safari. iOS 14.3 or later.
- Android Chrome and Samsung Internet. Evergreen, no specific minimum (all currently supported versions work).
Hybrid and WebView-based apps
The widget runs as-is inside a WebView, with no code changes required. Confirmed-working containers:
- Capacitor (Ionic, generic Capacitor apps).
- Cordova and PhoneGap.
- React Native with
react-native-webview. - Flutter with
webview_flutter.
Both data-voicegram-trigger and <meta name="voicegram-bubble"> work inside the WebView with no extra setup.
Microphone permission setup
The visitor's WebView must be granted microphone permission. This is a one-time install setup, but you have to declare it correctly in your app manifest or the WebView's getUserMedia call will fail silently:
- iOS. Add
NSMicrophoneUsageDescriptionto your app'sInfo.plistwith a customer-facing string explaining why the app needs the microphone. (Example: "Used to record voice messages.") Without this string, iOS terminates the app the first time the WebView prompts for the microphone. - Android. Add
<uses-permission android:name="android.permission.RECORD_AUDIO" />to yourAndroidManifest.xml. You will also need to request the permission at runtime (Android 6+) before the WebView attemptsgetUserMedia. Most modern WebView wrappers expose a runtime-permission API for this.
Pure native apps (not supported)
The widget is built with HTML, CSS, and JavaScript that runs in the DOM. It cannot run inside a pure-native Swift, SwiftUI, Kotlin, or Compose app.
If you need recording inside a pure-native app today, your options are:
- Wrap a web view around your existing site or contact page. This is the path most early customers take. The widget runs inside the WebView as documented above. Trivial to ship if you already have a site.
- Open a hosted recording page in
SFSafariViewController(iOS) orCustomTabsIntent(Android), then return to the app via deep link. No native UI required, but it does introduce a small in-app browser transition. We do not ship a turnkey integration for this today, but it is straightforward to build against the existing dashboard URLs. - Wait for a first-party native SDK. Native Swift and Kotlin packages that ship a native UI calling the same backend API. Not available today and would require new product work. If this is critical for your use case, contact us so we can prioritize against demand.
For most early customers, "wrap your contact page in a WebView" is the right answer and gets you 95% of the experience with zero extra build work.
Next steps
- Quickstart. The one-line install.
- Customization. Custom triggers and per-page bubble suppression.
- Troubleshooting. Recording-failure debugging on iOS Safari.