Important
Flutter Obfuscation issue
Migration from the track-event solution to the low-code solution:
- Refer to Step 2 in the installation guide, and verify the addition of the navigationObserver and clickListener.
- The migration process will take up to 24 hours to complete and be reflected in Pendo, during the processing time, you will not be able to tag Pages and Features.
Important
Requirements:
- Flutter: ">=3.16.0"
- SDK: ">=3.2.0 < 4.0.0"
- Android Gradle Plugin
7.2
or higher - Kotlin version
1.9.0
or higher - JAVA version
11
or higher - minSdkVersion
21
or higher - compileSDKVersion
33
or higher
Supported Navigation Libraries:
- GoRouter 13.0 or higher
- AutoRoute 7.0 or higher
-
In the application folder, run the following command:
flutter pub add pendo_sdk
-
In the application android/build.gradle file:
-
Add the Pendo Repository to the repositories section under the allprojects section or to the settings.gradle if using dependencyResolutionManagement:
allprojects { repositories { maven { url = uri("https://software.mobile.pendo.io/artifactory/androidx-release") } mavenCentral() }
-
Minimum SDK Version:
If applicable, set your app to be minSdkVersion 21 or higher:android { minSdkVersion 21 }
-
In the application AndroidManifest.xml file:
Add the following<uses-permission>
to the manifest in the<manifest>
tag:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-
Using ProGuard / R8
-
If you are using ProGuard, the rules that need to be added to ProGuard can be found here: pendo-proguard.cfg.
-
If you are using ProGuard(D8/DX only) to perform compile-time code optimization, and have
{Android SDK Location}/tools/proguard/proguard-android-optimize.txt
, add!code/allocation/variable
to the-optimizations
line in yourapp/proguard-rules.pro
file. The optimizations line should look like this:
-optimizations *other optimizations*,!code/allocation/variable
Note
The API Key
can be found in your Pendo Subscription Settings in App Details.
-
For optimal integration place the following code at the beginning of your app's execution:
import 'package:pendo_sdk/pendo_sdk.dart'; var pendoKey = 'YOUR_API_KEY_HERE'; await PendoSDK.setup(pendoKey);
-
Initialize Pendo where your visitor is being identified (e.g. login, register, etc.).
import 'package:pendo_sdk/pendo_sdk.dart'; final String visitorId = 'VISITOR-UNIQUE-ID'; final String accountId = 'ACCOUNT-UNIQUE-ID'; final Map<String, dynamic> visitorData = {'Age': '25', 'Country': 'USA'}; final Map<String, dynamic> accountData = {'Tier': '1', 'Size': 'Enterprise'}; await PendoSDK.startSession(visitorId, accountId, visitorData, accountData);
Notes:
visitorId: a user identifier (e.g. John Smith)
visitorData: the user metadata (e.g. email, phone, country, etc.)
accountId: an affiliation of the user to a specific company or group (e.g. Acme inc.)
accountData: the account metadata (e.g. tier, level, ARR, etc.)
Tip
To begin a session for an anonymous visitor, pass null
or an empty string ''
as the visitor id. You can call the startSession
API more than once and transition from an anonymous session to an identified session (or even switch between multiple identified sessions).
- Add Navigation Observers
When usingFlutter Navigator API
add PendoNavigationObserver for each app Navigator:import 'package:pendo_sdk/pendo_sdk.dart'; // Observes the MaterialApp/CupertinoApp main Navigator return MaterialApp( ... navigatorObservers: [ PendoNavigationObserver() ],); // Observes the nested widget Navigator return Navigator( ... observers: [ PendoNavigationObserver() ],);
Tip
The Pendo SDK uses the Route
name to uniquely identify each Route
. For the best practice please make sure to provide each route with unique name in the RouteSettings
. That should also be applied to the showModalBottomSheet
api.
Navigation Types:
-
GoRouter
When using
GoRouter
, change thesetup
API call to include the correct navigation library, like so:PendoSDK.setup(pendoKey, navigationLibrary: NavigationLibrary.GoRouter);
When using
GoRouter
, apply theaddPendoListenerToDelegate()
to yourGoRouter
instance.
Make sure to add it once (e.g adding it in the build method will be less desired)import 'package:pendo_sdk/pendo_sdk.dart'; final GoRouter _router = GoRouter()..addPendoListenerToDelegate() class _AppState extends State<App> { @override Widget build(BuildContext context) { return PendoActionListener( child: MaterialApp.router( routerConfig: _router, ), ); } }
Tip
Pendo SDK uses routerDelegate listener to track route change analytics, make sure your route is included in the GoRouter routes
-
AutoRoute
When using
AutoRoute
, change thesetup
API call to include the correct navigation library, like so:PendoSDK.setup(pendoKey, navigationLibrary: NavigationLibrary.AutoRoute);
When using
AutoRoute
, apply theaddPendoListenerToDelegate()
to yourAutoRoute.config()
instance.
Make sure to add it once (e.g adding it in the build method will be less desired)import 'package:pendo_sdk/pendo_sdk.dart'; @AutoRouterConfig() class AppRouter extends RootStackRouter { @override List<AutoRoute> get routes => []; } final AppRouter _router = AppRouter()..config().addPendoListenerToDelegate(); class _AppState extends State<App> { @override Widget build(BuildContext context) { return PendoActionListener( child: MaterialApp.router( routerConfig: _router.config(), ), ); } }
Tip
Pendo SDK uses routerDelegate listener to track route change analytics, make sure your route is included in the AutoRoute routes.
- Add a click listener
Wrap the main widget with a PendoActionListener in the root of the project:import 'package:pendo_sdk/pendo_sdk.dart'; Widget build(BuildContext context) { return PendoActionListener( // Use the PendoActionListener to track action clicks child: MaterialApp( title: 'Title', home: Provider( create: (context) => MyHomePageStore()..initList(), child: MyHomePage(title: Strings.appName), ), navigatorObservers: [PendoNavigationObserver()], // Use Pendo Observer to track the Navigator stack transitions ); ) }
Tip
You can use track events to programmatically notify Pendo of custom events of interest:
import 'package:pendo_sdk/pendo_sdk.dart';
await PendoSDK.track('name', { 'firstProperty': 'firstPropertyValue', 'secondProperty': 'secondPropertyValue'});
Note
The Scheme ID
can be found in your Pendo Subscription Settings in App Details.
This step enables guide testing capabilities.
Add the following activity to the application AndroidManifest.xml in the <Application>
tag:
<activity android:name="sdk.pendo.io.activities.PendoGateActivity" android:launchMode="singleInstance" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="YOUR_SCHEME_ID_HERE"/>
</intent-filter>
</activity>
- Test using Android Studio:
Run the app while attached to the Android Studio.
Review the Android Studio logcat and look for the following message:
Pendo SDK was successfully integrated and connected to the server.
- In the Pendo UI, go to Settings>Subscription Settings.
- Select the Applications tab and then your application.
- Select the Install Settings tab and follow the instructions under Verify Your Installation to ensure you have successfully integrated the Pendo SDK.
- Confirm that you can see your app as Integrated under subscription settings.
- Notes, Known Issues & Limitations.
- To support hybrid mode in Flutter, please open a ticket.
- For technical issues, please review open issues or submit a new issue.
- Release notes can be found here.
- For additional documentation, visit our Help Center Mobile Section.