Installing Activity Flow in Flutter apps
This guide explains how to install and configure the VTEX Activity Flow SDK in Flutter apps for Android and iOS.
Before you begin
Install the Activity Flow package
The Activity Flow SDK captures user navigation and sends events from your mobile app. To install the package, run the following command in your project directory:
_10flutter pub add activity_flow
This installs the SDK and updates your pubspec.yaml file with the activity_flow dependency.
Instructions
Step 1 – Importing the Activity Flow package
In your app's main file, import the Activity Flow package as follows:
_10import 'package:activity_flow/activity_flow.dart';
Step 2 – Creating an Activity Flow instance
Set the account name to create an instance of the main package class:
_13void main() {_13runApp(const MyApp());_13}_13_13class App extends StatelessWidget {_13_13 Widget build(BuildContext context) {_13_13// Call activity flow here_13 initActivityFlow(accountName: appAccountName);_13..._13_13}
Step 3 – Tracking page views automatically
To automatically track user navigation between app pages, add the PageViewObserver to the navigatorObservers list in your app:
_10MyApp(_10 // Add the PageViewObserver to the navigatorObservers list._10 navigatorObservers: [PageViewObserver()],_10 routes: {_10 // Define your named routes here_10 },_10_10),
This setup enables automatic screen view tracking for standard route navigation.
Step 4 – Tracking page views manually (for custom navigation)
For navigation widgets like BottomNavigationBar or TabBar, which do not trigger route changes, use the trackPageView function to track screen views manually.
For example, using the onTap callback within a BottomNavigationBar widget allows for capturing a new route each time the user taps on a different tab:
_12BottomNavigationBar(_12 items: items,_12 currentIndex: _selectedIndex,_12 selectedItemColor: Colors.pink,_12 onTap: (index) {_12 _onItemTapped(index);_12 final label = items[index].label ?? 'Tab-$index';_12_12 // Manually calling the `trackPageView` with the label_12 trackPageView(label);_12 },_12)
Step 5 – (Optional) Tracking ad events
Ads tracking is available only for accounts using VTEX Ads. If you're interested in this feature, open a ticket with VTEX Support.
To start tracking your ad events, follow these steps:
- Call the
addAdsListener
To track ad impressions, views, and clicks, use the addAdsListener extension method by attaching it to any widget that displays ads:
_10yourAdWidget.addAdsListener({Map<String, String> adMetadata);
yourAdWidget: The ad widget you want to monitor.adMetadata: A map containing specific details about the ad, which will be sent to your analytics service upon a click.
Flutter automated tests
To ensure your Flutter test runs work correctly when the Activity Flow is installed, run tests with a test environment flag using a --dart-define flag.
The --dart-define flag lets you pass compile-time key=value pairs into your Flutter app as Dart environment declarations. Follow the steps below:
- In your terminal, run
flutter test --dart-define=ACTIVITY_FLOW_TEST_ENV=true. - In a code editor, open your project.
- In the code editor settings, search for
dart.flutterTestAdditionalArgs. - Add to it the value
--dart-define=ACTIVITY_FLOW_TEST_ENV=true. - Open the
settings.jsonfile of your project. - Add the following:
"dart.flutterTestAdditionalArgs": ["--dart-define=ACTIVITY_FLOW_TEST_ENV=true"]
Use case example
Below is an example that contains an app with some pages and navigation through them:
_93import 'package:activity_flow/activity_flow.dart';_93import 'package:flutter/material.dart';_93import 'package:example/screens/favorite.dart';_93import 'package:example/screens/products.dart';_93import 'package:example/screens/profile.dart';_93_93void main() {_93 runApp(const ExampleApp());_93}_93/// A MaterialApp with a custom theme and routes._93/// The routes are defined in the [routes] property._93/// The theme is defined in the [theme] property._93class ExampleApp extends StatelessWidget {_93 const ExampleApp({super.key});_93_93 @override_93 Widget build(BuildContext context) {_93 initActivityFlow(accountName: appAccountName);_93_93 return MaterialApp(_93 title: 'Example App',_93 theme: ThemeData(_93 colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),_93 useMaterial3: true,_93 ),_93 routes: {_93 '/': (context) => const MyHomePage(),_93 '/products': (context) => const ProductsScreen(),_93 '/profile': (context) => const ProfileScreen(),_93 '/favorites': (context) => const FavoriteScreen(),_93 },_93 initialRoute: '/',_93 navigatorObservers: [PageViewObserver()],_93_93/// A home screen with buttons to navigate to other screens._93class MyHomePage extends StatelessWidget {_93 const MyHomePage({super.key});_93_93 final List<Map> _routes = const [_93 {_93 'name': 'Products',_93 'route': '/products',_93 },_93 {_93 'name': 'Profile',_93 'route': '/profile',_93 }_93 ];_93_93 @override_93 Widget build(BuildContext context) {_93 return Scaffold(_93 appBar: AppBar(_93 backgroundColor: Theme.of(context).colorScheme.inversePrimary,_93 title: const Text('Home Screen'),_93 ),_93 body: Center(_93 child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [_93 const AdBanner().addAdsListener({_93 'productName': 'Sneakers',_93 'productPrice': '59.99',_93 'adID': '1123',_93 }),_93 ..._routes.map((route) => ButtonTemplate(_93 title: route['name'],_93 route: route['route'],_93 )),_93 ])),_93 );_93 }_93}_93_93/// A template for creating buttons._93/// Receives a [title], [icon], and [route] to navigate to._93/// Returns an [ElevatedButton.icon] with the given parameters._93class ButtonTemplate extends StatelessWidget {_93 const ButtonTemplate({_93 super.key,_93 required this.title,_93 required this.route,_93 });_93_93 final String title;_93 final String route;_93_93 @override_93 Widget build(BuildContext context) {_93 return ElevatedButton(_93 onPressed: () => Navigator.pushNamed(context, route),_93 child: Text(title),_93 );_93 }_93}
The example demonstrates the integration of Activity Flow into a Flutter app by importing the necessary package, initializing it with initActivityFlow(accountName: appAccountName), and constructing a MaterialApp with named routes and a PageViewObserver to automatically capture page-view events.
It outlines a MyHomePage that incorporates an AdBanner, which utilizes addAdsListener to pass ad metadata such as product name, price, and ID. Additionally, it features navigation buttons sourced from a routes list.
The reusable ButtonTemplate facilitates navigation through Navigator.pushNamed, showcasing a standard configuration for automatic screen tracking, as well as ad impression and click tracking, in a Flutter application.