Keeping an eye out for issues that affect your app’s stability is crucial, but we also know that you can’t spend your entire day staring at the Firebase Crashlytics console.
From the beginning, Crashlytics has given developers the ability to turn on stability alerts so they can be notified when issues increase in impact and severity. Developers have the power to customize these notifications so they're delivered at the right time and channel for maximum visibility - channels where developers already spend their time.
In this blog post, we'll review the types of alerts Crashlytics provides and our recommendations on how to configure them based on observations from customers.
Let’s start by reviewing the different types of alerts Crashlytics sends. Currently, Crashlytics sends five alerts: new fatal issue, new non-fatal issue, trending issues, regression, and velocity alerts.
New issue alerts let you know the first time a new crash has occurred. We filter out the noise of repeated crashes, but give you the full stream of unique crashes by stack trace grouping. These alerts are turned off by default to avoid over inundating you, because as your app grows, you could get tons of alerts for every new version. We recommend turning these on for teams interested in knowing about every new type of crash, and for QA teams chasing down crashes found in testing versions of their apps.
Regression detection alerts you when a previously closed issue re-occurs in a new app version, which is a signal that something else may be awry and you should pay close attention to it.
Trending issues digest is sent out to developers in two instances 1) When Crashlytics detects a new crash is beginning to gain momentum (called emerging issues) 2) When Crashlytics detects new top crashes that have climbed to close to the top of your issue list recently (called trending issues). This daily email is on by default, and is a great way to keep track of emerging issues in your app.
One of the most important alerts within Crashlytics is the velocity alert, which notifies you when an issue suddenly increases in severity and impacts a significant percentage of your users. However, we recognize that every app is unique and the one-size-fits-all alerting threshold might not be what’s best for you and your business. That’s why you can now customize velocity alerts and determine how often and when you want to be alerted about changes to your app’s stability.
You can learn more about customizing velocity alerts here.
Now that you know the different notification types in Crashlytics, you can begin to build your alerting plan.
Firebase Crashlytics offers several channels to receive the above alerts. The first two channels are email and in-console alerts.
To setup these alerts:
Next, you can set up notifications through Slack, Jira or PagerDuty. To set up these alerts, you need to do two things: integrate Slack / Jira / PagerDuty with your Firebase project, and then choose your triggers.
For Slack:
There are two ways to create Jira issues from Crashlytics issues:
Here’s how you enable the Jira integration:
Our PagerDuty integration is setup similarly.
We find that a lot of our users get different utility out of each channel. In Slack, teams frequently set up a channel to show a real-time feed of all new issues, as a way to loosely monitor new issues coming up. Developers with an interest in specific pieces of code can then click through to get more detail on the issues they’re interested in. This is a pattern that seems to work well for most teams.
In Jira, we see developers using the manual integration option to create issues when they know their team is ready to take on that work. In addition, teams also setup automatic triggers for velocity alerts and regressions as those are known higher priority issues to look into.
And for PagerDuty, most teams focus on velocity alerts, which provide insight into the most critical situations your users are experiencing. For teams with even more custom use cases, we recommend developers integrate Crashlytics with Cloud Functions.
By setting up alerting in Crashlytics, you can rest assured that you’ll be alerted when critical issues occur in your app and be ready to take action when needed. For more about Crashlytics check out our docs here.
Notifications are all about getting the user’s attention at the right place and at the right time, leading them to the most important places in your app. Having richer content in your notifications can make them stand out to your users, and increase the chances that they engage with your app. In this blog post, we'll discuss several ways to make your notifications more interesting to your users by:
Recently, the Firebase Cloud Messaging team added image support for notifications on both iOS and Android platforms. We've also added 12 parameters on Android which let you easily craft fun and rich notifications with minimal effort.
You can now add images to your notifications, as shown in the figure below. These can help make your notifications a lot livelier, and provide a visual context for your notification that can match with your app. For example, if you're developing a video streaming app, a notification that includes movie poster images for new releases could be a great way for your notification to get more attention. If you're an e-commerce app developer, notifying your user with the picture of the product they've been waiting for could help encourage them to make the purchase.
Figure 1: Image notifications on iOS platform
Figure 2: On Android, images show up in both the notification tray when your notification is expanded, as well as when that notification is opened.
The first thing you need to do is to prepare a notification with an image URL. From the Firebase console, you’ll be presented with two options when you are composing a notification:
Option 1 - You can enter a URL to the image you want to use;
Option 2 - You can upload a local image directly to your notification composer.
If you are using the HTTP v1 API, you will need to provide a public URL to the image parameter in the JSON body for the notification you’re sending. If you like, you can use Cloud Storage for Firebase to upload an image and get a public URL for the image from there.
When you copy and paste the public image URL or upload your image directly to the notification composer, the newly updated notification composer will render a preview of the image on the notification for each platform, as shown in Figure 3.
Figure 3: The newly updated notification composer helps you easily visualize the image layout for your notifications
Download the latest Messaging SDKs for Android and iOS and rebuild your app with the new dependencies. When a notification that includes an image URL is delivered to the device, the messaging SDK will download the image and attach it to the notification. If the image cannot be downloaded due to the size of the image or availability of the network, the FCM client will display the notification without rendering the image.
Note that in order to send notifications with images or other media files on iOS, you will need to enable service extensions for the iOS platform. We’ll cover that next. If you are an Android developer, you’re already all set for sending notifications!
To receive notifications with media files in iOS, you will need to add a Notification Service Extension target in your project. The extension is available starting from iOS 10+ and supports media files like images, videos and gifs! To use videos and gifs, you will have to upload them to Cloud Storage for Firebase first and copy and paste the public URLs of those files in the Notification composer, or to the JSON image parameter in the HTTP v1 API.
When a notification is first received on a client device, the Notification Service Extension intercepts the message and allows developers to modify it before it becomes visible to users. At this point is when you will call the Firebase Messaging ExtensionHelper API to let the iOS SDK handle downloading and attaching the media files for you. Keep in mind, the processing time available for a service extension is short-lived, so if the media file is too big to download or process, the client might not complete attaching it to the notification before it is sent. When network availability is limited or slow, or the image is too large, the service extension might simply complete without an image included since it wasn’t able to finish downloading it.
You can follow these steps in Apple Documents to create a notification service extension target. Next, modify the last call in didReceiveNotificationRequest:withContentHandler: by doing the following: instead of completing it with the contentHandler(self.bestAttemptContent), call the FIRMessaging extensionHelper API. This will allow the Messaging SDK to handle downloading the image and completing the handler for you.
@interface NotificationService () <NSURLSessionDelegate> @property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver); @property(nonatomic) UNMutableNotificationContent *bestAttemptContent; @end @implementation NotificationService - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here as you wish self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; // Call FIRMessaging extension helper API. [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent withContentHandler:contentHandler]; }
Code sample on how to call FIRMessaging extension helper API to attach image to your notification.
Figure 4: An example of a gif notification received on iOS platform.
That’s it! Go ahead and start sending notifications with some fun images!
Firebase Cloud Messaging now gives you more options to enhance notifications and do things like enabling the default sound and vibration pattern, controlling whether your notifications show on locked screens or not, and more. To enable these features, you’ll just need to add additional parameters to your notifications using the HTTP Send API. Below are all the new parameters we’ve introduced in this release. You can check which Android API levels support which parameter features by checking out the documentation here.
{ "ticker" : "this is a ticker text", "event_time": "2000-01-01T00:00:00Z", // dismiss on click "sticky": false, // won't show on bridged devices such as Android wear watches. Only show on target device "local_only": true, // require the user's prompt attention. Ex: earthquake alert "priority": "PRIORITY_MAX", // vibrate pattern being off 1s, on 1s, off 4s, 8s "vibrate_timings": ["1s", "2s", "4s", "8s"], // won't show on a locked screen. Ex: no show on direct booted devices "visibility": "VISIBILITY_PRIVATE" "light_settings": "color": { "red": 0.2, // amount of red in the color "green": 0.4, // amount of green in the color "blue": 1 // amount of blue in the color "alpha": 0.8 // almost solid color }, "light_on_duration": "1s", "light_off_durtaion": "2s" } }
Let’s look at some new possibilities and use cases for different notifications using these new parameters!
Often, developers send notifications that inform users about events with an absolute time reference, like a limited-time sale a concert date. However, the time that the notification actually gets delivered may not always match up with the event time for the content of that notification. For instance, let’s say a short-lasting Firebase pizza sale notification is delivered to a device in airplane mode. When the device regains connectivity, the notification will be displayed with a timestamp of the time the notification was received as the device got back online. That received notification time will be misleading if the sale has already expired, leaving the user misinformed.
By default, notifications are time-stamped with the system time at the moment they are received on the device. If they are not the time value you wish to have for your notifications, you can override the timestamp value by setting event_time. In addition, setting event_time can be useful since notifications are sorted in the notification drawer by the event time indicating when they were received. For example, if you're a sports app developer and send play by plays for major games via notifications to your users, you'll want these to show up in chronological order in the notification tray for your users. Setting event_time will help you accomplish just that.
event_time
Note that to represent a point in time independent of any time zone or calendar, we use the UTC Epoch time defined by the Timestamp object.
Most modern Android devices have vibration capabilities and some have LED lights that can be used for notifications. These can provide physical and visual cues for your customers to distinguish your app from others. You can set both settings with the light_settings and vibrate_timings parameters.
light_settings
vibrate_timings
If you want to set a sound and vibrate pattern for a notification without spending a lot of time configuring it, just set defaultSound and defaultVibrateTimings to true and you’ll be set to go.
defaultSound
defaultVibrateTimings
Like all other information, notifications have varying levels of importance.The higher the importance of a notification, the more prioritized and interruptive notifications will be. You can set notification importance by setting notification_priority.
notification_priority
Note that notification_priority is different from AndroidMessagePriority. The former one controls the UI behavior of the notifications on the device. The latter one is an FCM concept that controls when the message is delivered. See FCM guides for more information.
AndroidMessagePriority
Some notifications may carry sensitive content. As a developer, you might want to control the level of visibility for notifications posted by your app on a secure locked screen. Now you can set visibility to control how notifications are displayed on a locked screen.
visibility
Figure 5. Notifications on the lock screen with sensitive content hidden
By default, each notification received for your app increments a notification number displayed on the long-press menu for your app launcher icon , but you can override this number for your app. For example, this might be useful if you're using just one notification to represent multiple new messages but you want the count here to represent the number of total new messages. You can set the notification count by setting the field of “notification_count”
Figure 6 Notification badges and the long-press menu with notification count
We highly recommend that you start incorporating images into your notifications to make them richer and more engaging on iOS and Android, and enhancing them even further with notification parameters for Android ! As always, if you have any questions or feedback from us, please reach out on StackOverflow or our official support page.
Hello Firebase Developers!
We recently launched a major refresh for the Remote Config SDK in our v2 release, and it includes a few changes that will help you keep your app responsive and snappy.
The tl,dr; is that in the v2 SDK we’ve improved Remote Config along the following themes:
Read on for more details on each of these new updates!
One of the biggest requests we’ve had is to add non-blocking initialization and fetch calls for Remote Config params, and for good reason.
Let’s say you’re a developer for a travel app, and you want to show a travel deal based on whether a customer is predicted to spend on hotels at some destination (possibly using Firebase Predictions). With Remote Config, you can surface such travel deals to just those users. Now, let’s say that these deals are surfaced alongside the main parts of your app, where your users find and book travel. What you don’t want is for your users to have to wait for these main parts of your app to get blocked on Remote Config initialization for those travel deals. With the v1 SDK, unless you were very careful about where you placed your Remote Config initialization call, your users would have to wait for Remote Config initialization before being able to use the main parts of the app. In the v2 SDK, this is no longer the case.
By introducing non-blocking initialization, it is now possible to load Remote Config without affecting the load time of the rest of the app. This can improve startup times across the board, but is especially important for users who are in regions of limited or slow network connectivity.
We’ve also added a new convenience method in the V2 SDKs to both fetch and activate your Remote Config values in a single call, which streamlines the activation code flow. Here are how the new calls look for fetching and activating Remote Config parameters before and after the v2 SDK updates:
iOS:
// BLOCKING remoteConfig = RemoteConfig.remoteConfig() // Fetch with a completion handler. remoteConfig.fetch { status, error in if status == .success { remoteConfig.activateFetched() let value = remoteConfig[“myKey”]; } }
// Non-blocking initialization. remoteConfig = RemoteConfig.remoteConfig() remoteConfig.fetchAndActivate { (status, error) in if status == .successFetchedFromRemote || status ==.successUsingPreFetchedData { let value = remoteConfig[“myKey”]; } }
Android:
// BLOCKING FirebaseRemoteConfig frc = FirebaseRemoteConfig.getInstance(); frc.fetch() .addOnSuccessListener(new …<>() { frc.activateFetched(); readFrcValues(); }); void readFrcValues() { value = frc.getInteger(“myKey”); }
// Non-blocking initialization. // Loads values from disk asynchronously. FirebaseRemoteConfig frc = FirebaseRemoteConfig.getInstance(); frc.fetchAndActivate().addOnSuccessListener((unusedVoid) -> readFrcValues()); void readFrcValues() { value = frc.getInteger(“myKey”); }
Another important update for smarter fetching is the introduction of the new FetchTimeoutInSeconds and MinimumFetchIntervalInSeconds parameters, which can be used together to provide smarter fetching policies for your app.
The FetchTimeoutInSeconds parameter is useful when you don’t want your application to wait longer than X seconds to fetch new Remote Config values. It sounds like a small change, but this can actually make a considerable difference in how you build a responsive app for your users.
For example, let’s go back to the travel app. The travel deals portion of the app is conditioned on Remote Config values, but this is for a non-critical part of the app. It doesn’t get in the way of the main booking flow in the app, so it’s not as important if the travel deals load up and show immediately after the user opens the app.
Now let’s say we’ve designed a new booking flow for our app, and want to roll it out to a test group to get some feedback. In this scenario, users will need to wait for a network roundtrip to the Remote Config backend to determine if they’ll get the new booking interface for the test group, or the current booking interface instead.
Waiting for one roundtrip for the interface to load isn’t generally a huge deal, but what if our user is in an area of limited or spotty connectivity? In such cases, the reliability or availability of network infrastructure can dictate the user experience we can provide.
This situation is where being able to set the FetchTimeoutInSeconds becomes really useful. Let’s say we don’t want the test group to experience any Remote Config fetch delays greater than three seconds. Well, using this parameter we can specify exactly that. So if our user does happen to be in an area with spotty network connectivity, we can still ensure they can have a great experience by falling back to either the previously fetched values or the default values.
The new MinimumFetchIntervalInSeconds parameter, as the name implies, allows you to set the minimum interval for which you want to check for any new Remote Config parameter values.
The new parameter name better describes how Remote Config handles retrieving new parameter values from the RC backend over the previous caching terminology, but does not change how Remote Config handles caching. If the default minimum fetch interval of 12 hours is too long for your app’s needs, you can adjust it to a value that’s more appropriate for your app, such as once per hour.
Keep in mind that going beyond that might cause your app to run into rate limits. In case you do hit a rate limit, though, the new error response codes can help deal with that (read the section below for more details).
Setting up these new parameters is straightforward. On Android, you can set both the minimum fetch interval and the fetch timeout parameters directly with the Settings Builder API:
Android
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder() .setMinimumFetchIntervalInSeconds(fetchRefreshRate) .setFetchTimeoutInSeconds(fetchTimeout) .build(); mFirebaseRemoteConfig.setConfigSettings(configSettings);
On iOS, you can set similar values on the configSettings object.
configSettings
iOS
let remoteConfigSettings = RemoteConfigSettings() remoteConfigSettings.minimumFetchInterval = 1200 remoteConfigSettings.fetchTimeout = 3 remoteConfig.configSettings = remoteConfigSettings
To enable development mode using the new MinimumFetchIntervalInSeconds parameter, just set the parameter value to 0. Just be sure to set this back before you ship to production!
MinimumFetchIntervalInSeconds
For the Android SDK, we’ve updated how the client SDK communicates with the Remote Config backend. The Remote Config SDK’s previous implementation sometimes resulted in error responses getting eaten up along the way. This would sometimes make it difficult to understand why fetch requests were failing. Providing more informative and meaningful error messages is now improved by replacing networking calls through direct REST API calls to the Remote Config backend. So you’ll now be able to get more meaningful error responses when something goes wrong.
Upgrading is easy! Just update your Remote Config dependencies to the latest version, rebuild your app, and you’ll be set up to use the latest Remote Config V2 SDKs.
We’re always trying to improve and make Remote Config, as well as each of our other Firebase products, more helpful and easier to use. These changes are an effort towards that, so let us know what you think about them! Also, if you discover any bugs with the new updates, we’d love to hear about those too. Please reach out to us on StackOverflow or the official Firebase support site.
That’s right, the Android SDK and the iOS SDK for Remote Config are now both open source! You can check out the GitHub repo for the Android SDK in all its open source goodness here, and the repo for the iOS SDK here.
This article originally appeared in the Firebase Developer Community blog.
We like saying lots of impressive things about Cloud Firestore's performance -- "performance scales with the size of the result set, not the underlying data set", and that "it's virtually impossible to create a slow query." And, for the most part, this is true. You can query a data set with billions upon billions of records in it, and get back results faster than your user can move their thumb away from the screen.
But with that said, we occasionally hear from developers that Cloud Firestore feels slow in certain situations, and it takes longer than expected to get results back from a query. So why is that? Let's take a look at some of the most common reasons that Cloud Firestore might seem slow, and what you can do to fix them.
Probably the most common explanation for a seemingly slow query is that your query is, in fact, running very fast. But after the query is complete, we still need to transfer all of that data to your device, and that's the part that's running slowly.
So, yes, you can go ahead and run a query of all sales people in your organization, and that query will run very fast. But if that result set consists of 2000 employee documents and each document includes 75k of data, you have to wait for your device to download 150MB of data before you can see any results.
The best way to fix this issue is to make sure you're not transferring down more data than you need. One simple option is to add limits to your queries. If you suspect that your user only needs the first handful of results from your employee list, add a limit(25) to the end of your query to download just the first batch of data, and then only download further records if your user requests them. And, hey, it just so happens I have an entire video all about this!
limit(25)
If you really think it's necessary to query and retrieve all 2000 sales employees at once, another option is to break those records up into the documents that contain only the data you'll need in the initial query, and then put any extra details into a separate collection or subcollection. Those other documents won't get transferred on that first fetch, but you can request them later as your user needs them.
Having smaller documents is also nice in that, if you have a realtime listener set up on a query and a document is updated, the changed document gets sent over to your device. So by keeping your documents smaller, you'll also have less data transferred every time a change happens in your listeners.
So Cloud Firestore's offline cache is pretty great. With persistence enabled, your application "just works", even if your user goes into a tunnel, or takes a 9-hour plane flight. Documents read while online will be available offline, and writes are queued up locally until the app is back online. Additionally, your client SDK can make use of this offline cache to avoid downloading too much data, and it can make actions like document writes feel faster. However Cloud Firestore was not designed as an "offline first" database, and as such, it's currently not optimized for handling large amounts of data locally.
So while Cloud Firestore in the cloud indexes every field in every document in every collection, it doesn’t (currently) build any of those indexes for your offline cache. This means that when you query documents in your offline cache, Cloud Firestore needs to unpack every document stored locally for the collection being queried and compare it against your query.
Or to put it another way, queries on the backend scale with the size of your result set, but locally, they kinda scale with the size of the data in the collection you're querying.
Now, how slow local querying ends up being in practice depends on your situation. I mean, we're still talking about local, non-network operations here, so this can (and often is) faster than making a network call. But if you have a lot of data in one single collection to sort through, or you're just running on a slow device, local operations on a large offline cache can be noticeably slower.
First, follow the best practices mentioned in the previous section: add limits to your queries so you're only retrieving the data that you think your users will need, and consider moving unneeded details into subcollections. Also, if you followed the "several subcollections vs a separate top level collection" discussion at the end of my earlier post, this would be a good argument for the "several subcollections" structure, because the cache only needs to search through the data in these smaller collections.
Second, don't stuff more data in the cache than you need. I've seen some cases where developers will do this intentionally by querying a massive number of documents when their application first starts up, then forcing all future database requests to go through the local cache, usually in a scheme to reduce database costs, or make future calls faster. But in practice, this tends to do more harm than good.
Third, consider reducing the size of your offline cache. The size of your cache is set to 100MB on mobile devices by default, but in some situations, this might be too much data for your device to handle, particularly if you end up having most of your data in one massive collection. You can change this size by modifying the cacheSizeBytes value in your Firebase settings, and that's something you might want to do for certain clients.
Fourth, try disabling persistence entirely and see what happens. I generally don't recommend this approach -- as I mentioned earlier, the offline cache is pretty great. But if a query seems slow and you don't know why, re-running your app with persistence turned off can give you a good idea if your cache is contributing to the problem.
So zig-zag merge joins, in addition to being my favorite algorithm name ever, are very convenient in that they allow you to coalesce results from different indexes together without having to rely on a composite index. They essentially do this by jumping back and forth between two (or more) indexes sorted by document ID and finding matches between them.
But one quirk about zig-zag merge joins is that you can run into performance issues where both sets of results are quite large, but the overlap between them is small. For example, imagine a query where you were looking for expensive restaurants that also offered counter service.
restaurants.where('price', '==', '$$$$').where('orderAtCounter', '==', 'true')
While both of these groups might be fairly large, there's probably very little overlap between them. Our merge join would have to do a lot of searching to give you the results you want.
So if you notice that most of your queries seem fast, but specific queries are slow when you're performing them against multiple fields at once, you might be running into this situation.
If you find that a query across multiple fields seems slow, you can make it performant by manually creating a composite index against the fields in these queries. The backend will then use this composite index in all future queries instead of relying on a zig zag merge join, meaning that once again this query will scale to the size of the result set.
While Cloud Firestore has more advanced querying capabilities, better reliability, and scales better than the Firebase Realtime Database, the Realtime Database generally has lower latency if you're in North America. It's usually not by much, and in something like a chat app, I doubt you would notice the difference. But if you have an app that's reliant upon very fast database responses (something like a real-time drawing app, or maybe a multiplayer game), you might notice that the Realtime Database feels… uhh… realtime-ier.
If your project is such that you need the lower latency that the Realtime Database provides (and you're anticipating that most of your customers are in North America), and you don't need some of the features that Cloud Firestore provides, feel free to use the Realtime Database for those parts of your project! Before you do, I would recommend reviewing this earlier blog post, or the official documentation, to make sure you understand the full set of tradeoffs between the two.
Remember that even in the most perfect situation, if your Cloud Firestore instance is hosted in Oklahoma, and your customer is in New Delhi, you're going to have at least 80 milliseconds of latency because of that whole "speed of light" thing. And, realistically, you're probably looking at something more along the lines of a 242 millisecond round trip time for any network call. So, no matter how fast Cloud Firestore is to respond, you still need time for that response to travel between Cloud Firestore and your device.
First, I'd recommend using realtime listeners instead of one-time fetches. This is because using realtime listeners within the client SDKs gives you a lot of really nice latency compensation features. For instance, Cloud Firestore will present your listener with cached data while it's waiting for the network call to return, giving you the ability to show results to your user faster. And database writes are applied to your local cache immediately, which means that you will see these changes reflected nearly instantly while your device is waiting for the server to confirm them.
Second, try to host your data where the majority of your customers are going to be. You have the option of selecting your Cloud Firestore location when you first initialize your database instance, so take a moment to consider what location makes the most sense for your app, not just from a cost perspective, but a performance perspective as well.
Third, consider implementing a reliable and cheap global communication network based on quantum entanglement, allowing you to circumvent the speed of light. Once you've done that, you probably can retire off of the licensing fees and forget about whatever app you were building in the first place.
So the next time you run into a Cloud Firestore query that seems slow, take a look through this list and see if you might be hitting one of these scenarios. While you're at it, don't forget that the best way to see how well your app is performing is to measure its performance out in the wild in real-life conditions, and Firebase Performance Monitoring is a great way of doing that. Consider adding Performance Monitoring to your app, and setting up a custom trace or two so you can see how your queries perform in the wild.
Analytics is the key to understanding your app's users: Where are they spending the most time in your app? When do they churn? What actions are they taking? To answer these questions, you need the right set of tools – and that’s why analytics has been a core part of Firebase since the beginning… and today, we’re excited to share with you that we’re adding more to our solution to help take app analytics to the next level!
Thanks to our continued partnership with Google Analytics, you can now upgrade your Firebase projects to the next generation of app analytics! This seamless upgrade requires no code changes and unlocks exciting new features while preserving data continuity. Now you can enjoy both the intuitive dashboards and free and unlimited event reporting you’re already enjoying in the Firebase console and all new capabilities to help you understand your user journeys in Google Analytics.
At a glance, here are some of the new capabilities and features you’ll be able to access in Google Analytics after making the upgrade:
The process for upgrading your existing Firebase project to the next generation Google Analytics experience is easy. Just follow the steps below to make the upgrade:
From that point, you’ll be able to access these new features in Google Analytics.
The upgrade will be available to all Firebase users over the coming weeks.
Yes! This upgrade enables a lot of new features and reports you will be able to access in Google Analytics, but will not affect your existing Firebase project analytics data in the Firebase console. You will be able to continue using the same dashboard and workflows you’re using today after the upgrade, but you’ll also have access to some advanced features in Google Analytics. Note that if you decide to enable cross-device reporting after making the upgrade, some user counts in your analytics data in the Firebase console may go down as the data will be de-duplicated with User-ID.
Cross-device reporting and unified analytics with User-ID will be available in both Google Analytics and the Analytics dashboard in the Firebase console.
To enable cross-device reporting for both, check out this article on implementing the User-ID in analytics. You can then update your Google Analytics settings in the Firebase console to view your reports using this property to enable cross-device reporting.
We are excited about the benefits this next generation app analytics experience will unlock for you, and look forward to hearing your feedback as you try out these new features!