Getting Started with AWS

Build a Flutter Application

Create a simple Flutter application using AWS Amplify

Module 5: Add an Analytics Category

In this module you will add an Analytics category, create custom events, and view your analytics being tracked.

Introduction

The Photo Gallery app is now fully functional with the ability to authenticate a user and allow them to take pictures that are uploaded to Storage. Now we need to focus on recording analytics to understand how users are interacting with our app.

In this module, we will add the Analytics category to our Amplify app, create custom analytics events, implement those events, and view the Amazon Pinpoint dashboard to see our analytics being tracked.

What You Will Learn

  • Create the Analytics category
  • Record analytics events to Amazon Pinpoint
  • View the Amazon Pinpoint dashboard

Key Concepts

Analytics - Recording when events occur for each instance of the app can be a valuable way to collect analytics on user behavior, leading to a better understanding of what features are most important to the app.

 Time to Complete

10 minutes

 Services Used

Implementation

  • Create the Analytics Service

    Add the Analytics service to your Amplify project by running the following in the terminal at the root directory of your project:

    amplify add analytics

    The Amplify CLI will ask a series of questions to configure the Analytics service. Press the enter key to provide the default answer to each question. The output should look like this:

    ➜  photo_gallery git:(master) ✗ amplify add analytics
    ? Select an Analytics provider Amazon Pinpoint
    ? Provide your pinpoint resource name: photogallery
    Adding analytics would add the Auth category to the project if not already added.
    ? Apps need authorization to send analytics events. Do you want to allow guests
    and unauthenticated users to send analytics events? (we recommend you allow this
     when getting started) Yes

    After the resource is fully configured, you will receive an output like the following:

    Successfully updated auth resource locally.
    Successfully added resource photogallery locally

    Take note that adding Analytics will update our Auth category. We will be able to confirm this before configuring out backend by running:

    amplify push

    We should get a status report of the changes made to our Amplify app:

    ➜  photo_gallery git:(master) ✗ amplify push
    ✔ Successfully pulled backend environment dev from the cloud.
    
    Current Environment: dev
    
    | Category  | Resource name        | Operation | Provider plugin   |
    | --------- | -------------------- | --------- | ----------------- |
    | Analytics | photogallery         | Create    | awscloudformation |
    | Auth      | photogallery42b5391b | Update    | awscloudformation |
    | Storage   | s33daafe54           | No Change | awscloudformation |
    ? Are you sure you want to continue? Yes

    After the Analytics resource is configured in the backend, you should see a success message along with a link to your app's Pinpoint dashboard:

    ✔ All resources are updated in the cloud
    
    Pinpoint URL to track events https://us-west-2.console.aws.amazon.com/pinpoint/home/?region=us-west-2#/apps/ca14fce9dd034d6dbd7ca3ec27afc67c/analytics/overview
    

    Click the link to view the dashboard. It should look like this:

    FlutterApp-Module5Photo1

    We will revisit the dashboard after recording a few analytic events.

  • Install the Dependency

    In Visual Studio Code, open pubspec.yaml and add Amplify Analytics as a dependency:

    ... # amplify_storage_s3: '<1.0.0'
    
    amplify_analytics_pinpoint: '<1.0.0'
    
    ... # cached_network_image: ^2.3.3

    Now save the file to have Visual Studio Code install the Amplify Auth Cognito plugin. You can also run $ flutter pub get from the terminal if the dependency isn't installed on save.

    You should get an output of:

    exit code 0
  • Configure the Plugin

    Open main.dart and add the Analytics plugin to the instance of Amplify used to configure the other plugins:

    ... // void _configureAmplify() async {
    
    _amplify.addPlugin(
        authPlugins: [AmplifyAuthCognito()],
        storagePlugins: [AmplifyStorageS3()],
        analyticsPlugins: [AmplifyAnalyticsPinpoint()]);
    
    ... // try {

    Run the app. You should still see the success message in the logs indicating that Amplify is still properly configured and is including the Analytics plugin.

    flutter: Successfully configured Amplify 🎉
  • Implement Functionality

    Amplify Analytics makes it extremely easy to record analytics events by doing something like:

    final myEvent = AnalyticsEvent('my_event_name');
    myEvent.properties.addStringProperty('property_name', 'property_value');
    Amplify.Analytics.recordEvent(event: myEvent);

    However, defining and creating events at arbitrary points in the app can become tedious to maintain. Instead, we will define all the analytics events in a single file and make each event its own object.

    Create a new file called analytics_events.dart and add the following:

    import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart';
    
    abstract class AbstractAnalyticsEvent {
      final AnalyticsEvent value;
    
      AbstractAnalyticsEvent.withName({String eventName})
          : value = AnalyticsEvent(eventName);
    }
    
    class LoginEvent extends AbstractAnalyticsEvent {
      LoginEvent() : super.withName(eventName: 'login');
    }
    
    class SignUpEvent extends AbstractAnalyticsEvent {
      SignUpEvent() : super.withName(eventName: 'sign_up');
    }
    
    class VerificationEvent extends AbstractAnalyticsEvent {
      VerificationEvent() : super.withName(eventName: 'verification');
    }
    
    class ViewGalleryEvent extends AbstractAnalyticsEvent {
      ViewGalleryEvent() : super.withName(eventName: 'view_gallery');
    }

    By creating AbstractAnalyticsEvent, we can create custom analytics event objects that all have a common property, value, which will contain the AnalyticsEvent instance. With one line of code, we will be able to instantiate an AbstractAnalyticsEvent while keeping the implementation details in a single file.

    We can take this one step further. Let's create an AbstractAnalyticsEvent for when a user takes a picture, but let's also give it the ability to track whether the user used the front or back camera of their device. To be able to accomplish this, we first need to add another constructor to AbstractAnalyticsEvents accepts an AnalyticsEvent as a parameter.

    ... // : value = AnalyticsEvent(eventName);
    
    AbstractAnalyticsEvent.withEvent({AnalyticsEvent event}) 
          : value = event;
    
    ... // AbstractAnalyticsEvent closing }

    Now we can implement TakePictureEvent:

    class TakePictureEvent extends AbstractAnalyticsEvent {
      // 1
      TakePictureEvent._fromEvent(AnalyticsEvent event)
          : super.withEvent(event: event);
    
      // 2
      factory TakePictureEvent({@String cameraDirection}) {
        final event = AnalyticsEvent('take_picture');
        event.properties.addStringProperty('camera_direction', cameraDirection);
        return TakePictureEvent._fromEvent(event);
      }
    }
    1. We create a private constructor called _fromEvent which will allow us to call the super constructor that accepts an AnalyticsEvent as a parameter.
    2. The factory constructor will be the one we use to create this event and accepts a String parameter, allowing a camera direction to be included as a property of the AnalyticsEvent.

    Now let's create an object with the ability to turn an instance of our AbstractAnalyticsEvent into an AnalyticsEvent. Create a new file called analytics_service and add the following:

    import 'package:amplify_core/amplify_core.dart';
    import 'analytics_events.dart';
    
    class AnalyticsService {
      static void log(AbstractAnalyticsEvent event) {
        Amplify.Analytics.recordEvent(event: event.value);
      }
    }

    The AnalyticsService is simple, it has a static method called log which will take an AbstractAnalyticsEvent and pass the value to Amplify.Analytics. That's it.

    Now we can implement each of our concreate AbstractAnalyticsEvent classes.

    Add LoginEvent to the _login function in login_page.dart:

    ... // widget.didProvideCredentials(credentials);
    
    AnalyticsService.log(LoginEvent());
    
    ... // _login closing }

    Add SignUpEvent to the _signUp function in sign_up_page.dart:

    ... // widget.didProvideCredentials(credentials);
    
    AnalyticsService.log(SignUpEvent());
    
    ... // _signUp closing }

    Add VerificationEvent to the _verify function in verification_page.dart:

    ... // widget.didProvideVerificationCode(verificationCode);
    
    AnalyticsService.log(VerificationEvent());
    
    ... // _verify closing }

    Add ViewGalleryEvent to the constructor in gallery_page.dart:

    ... // : super(key: key) {
    
    AnalyticsService.log(ViewGalleryEvent());
    
    ... // constructor closing }

    Lastly, add TakePictureEvent to _takePicture in camera_page.dart:

    ... // widget.didProvideImagePath(path);
    
    AnalyticsService.log(TakePictureEvent(
        cameraDirection: widget.camera.lensDirection.toString()));
    
    ... // } catch (e) {

    We're able to pass the lensDirection to our event since the constructor takes a string arguement.

    Run through the app and try to hit all of the different events so they are recorded at least once.

    Once you've triggered some of the analytics events to be recorded, head over to the Pinpoint dashboard. If you've closed that window, you can get back by running the following:

    amplify console

    You should see the overview of you Amplify project:

    FlutterApp-Module5Photo2

    Navigate to the Analytics tab and click the "View in Pinpoint" button:

    FlutterApp-Module5Photo3

    Navigate to the analytics events section and you should be able to see how many analytics events were recorded:

    FlutterApp-Module5Photo4

    In this case, I was able to trigger 20 different events in the Photo Gallery app, showing that we have successfully implemented Amplify Analytics into our app.

    Feel free to add even more analytics or make the current ones more verbose. Then you'll be able to really understand how users interact with your app so you know which areas to focus on improving.

Conclusion

You have built a Flutter application using AWS Amplify! Now that the Photo Gallery is finished and you have implemented the Authentication, Storage, and Analytics services, there are only a few routes to go from here: make the code publicly viewable, expand the project to a different platform, or delete the project.

In this module, we will explore the steps required to go down each of these routes.

  • Securely Share Your Project

    If you're looking to make the Photo Gallery app viewable by others by hosting the code on a public repo or accessible to others in general, it is recommended that you remove sensitive information from your project that could lead to your AWS resources being abused. Most of the sensitive files should already be listed in .gitignore, but it is recommended you ensure these two lines are included in your repo:

    amplify/
    **/amplifyconfiguration.dart

    These lines will ensure that the amplify directory and the amplifyconfiguration.dart file are not included when pushing your code to a repo.

  • Sharing Your Backend

    AWS Amplify makes it easy to share your configure Amplify backend across multiple platforms or with team members. If you're looking to creating the app on a new platform, web for example, simply navigate to the root directory of your project and run the following command:

    ? Do you want to use an AWS profile? Yes
    ? Please choose the profile you want to use default
    ? Which app are you working on? d3p0ir7eqcu4le
    Backend environment 'dev' found. Initializing...
    ? Choose your default editor: Visual Studio Code
    ? Choose the type of app that you're building javascript
    Please tell us about your project
    ? What javascript framework are you using react
    ? Source Directory Path:  src
    ? Distribution Directory Path: build
    ? Build Command:  npm run-script build
    ? Start Command: npm run-script start
    
    ? Do you plan on modifying this backend? Yes

    The above is the output if you were to choose a JavaScript platform with React.

    You would still run $ amplify pull if you intend to work on a team, but the team member would need to have access to the same AWS profile where the Photo Gallery Amplify app is stored.

  • Deleting the Project

    If you're finished with the project and don't intend on working on it any further, you should consider deleting the Amplify app. This ensures that your resources wont be abused in the event someone gains access to your projects' credentials.

    To delete all the local Amplify associated files and the Amplify project in the backend, run the following command:

    amplify delete

    If you follow through on deleting the Amplify project, you will get an output like this:

    ✔ Project deleted in the cloud
    Project deleted locally.

    ⚠️ This action cannot be undone. Once the project is deleted, you cannot recover it and will have to reconfigure the categories and the project configuration files if you need to use the project again.

Thank you for having followed this tutorial until the end. Please let us know your feedback by using the tool below.

Was this module helpful?

Thank you
Please let us know what you liked.
Close
Sorry to disappoint you
Is something out-of-date, confusing or inaccurate? Please help us improve this tutorial by providing feedback.
Close

Congratulations!

You successfully built a Flutter application on AWS! As a great next step, dive deeper into specific AWS technologies and take your application to the next level.