Documentation
Feedback
Guides

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:


_10
flutter 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:


_10
import '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:


_13
void main() {
_13
runApp(const MyApp());
_13
}
_13
_13
class 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:


_10
MyApp(
_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:


_12
BottomNavigationBar(
_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:

  1. Call the addAdsListener

To track ad impressions, views, and clicks, use the addAdsListener extension method by attaching it to any widget that displays ads:


_10
yourAdWidget.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:

  1. In your terminal, run flutter test --dart-define=ACTIVITY_FLOW_TEST_ENV=true.
  2. In a code editor, open your project.
  3. In the code editor settings, search for dart.flutterTestAdditionalArgs.
  4. Add to it the value --dart-define=ACTIVITY_FLOW_TEST_ENV=true.
  5. Open the settings.json file of your project.
  6. 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:


_93
import 'package:activity_flow/activity_flow.dart';
_93
import 'package:flutter/material.dart';
_93
import 'package:example/screens/favorite.dart';
_93
import 'package:example/screens/products.dart';
_93
import 'package:example/screens/profile.dart';
_93
_93
void 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.
_93
class 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.
_93
class 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.
_93
class 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.

Contributors
1
Photo of the contributor
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
1
Photo of the contributor
Was this helpful?
Suggest edits (GitHub)
On this page