After taking a hiatus in 2020, Google I/O is back and we’re excited to take part in this revamped, digital event to share the updates we’ve made to Firebase. Over the past year, apps helped us adapt and thrive in our new circumstances, and apps will no doubt continue to play an important role for many years to come. Our mission is to empower developers like you to succeed by providing the resources and technology you need to unblock innovation in ways big and small, so you can focus on building and scaling the apps that people rely on.
We’re happy to share that now, over 3 million apps actively use Firebase every month, including large global businesses and fast-growing startups. Your trust in us is what motivates us to make Firebase even better. Today at Google I/O 2021, we’re unveiling updates to our platform that will help you accelerate app development, run your app more effectively, and optimize your user experience so you can grow your business. Read on for more, and don’t forget to check out the What’s New in Firebase session.
Hop to a particular section if you’re short on time, or read the entire blog.
Accelerate app development with new building blocks
Gain actionable insights to run your app efficiently
Optimize your user experience to scale with ease
We’re continuing to invest in tools that save you time so you can focus on the things you love and deliver value to your users, faster.
The Storage Emulator joins the Emulator Suite for broader backend coverage
The Emulator Suite lets you run emulated versions of our backend products on your own machine, enabling rapid iteration without interfering with production data or incurring costs. A few months ago, we added support for Firebase Authentication and now, we’re pleased to announce that Cloud Storage for Firebase is also joining the Emulator Suite, giving you broader coverage of our backend products. With the Storage Emulator, you can upload, download, and modify files as you would in production. It also interacts seamlessly with the other emulators, so you can trigger Cloud Functions for Firebase and protect access to your files with Firebase Authentication, all while developing and testing locally on your desktop machine. To use the Emulator Suite, download the Firebase CLI and launch the emulators on your machine or check out our documentation.
The Emulator Suite now includes Firebase Storage
Firebase App Distribution now supports Android App Bundles for streamlined testing
Firebase App Distribution makes it easy to distribute pre-release versions of your app to trusted testers so you can get valuable feedback before launch. App Distribution lets you manage all of your pre-release builds for both iOS and Android in a central hub, and it gives you the flexibility to distribute these builds right from the console or using the command-line tools that are already part of your workflow - like Gradle, Firebase CLI, and fastlane. Today, we’re adding support for Android App Bundles! Now, you can test the actual binaries that Android users install on their devices. App Bundles are the future of publishing on Google Play; by launching this feature, our goal is to make the transition as simple and smooth as possible for you. To learn more about Android App Bundle releases with App Distribution, check out the docs.
You can now distribute AAB releases with Firebase App Distribution
Strengthening app security with App Check
Keeping your infrastructure and users safe is an important priority for us. That’s why we’re excited to announce that App Check, a powerful new security feature, is now available in beta. App Check is an additional layer of security that protects access to your services by verifying that incoming traffic is coming from your app, and blocking traffic that doesn't have valid credentials. Right now, App Check is available for Cloud Storage, Realtime Database, and Cloud Functions for Firebase, and we’ll be expanding it to other products soon! Register your app with App Check and start enforcing protections through the Firebase console. To learn more about App Check, check out our documentation.
Start protecting your app and user data with App Check
New modularized Web SDKs improve load times
In addition to adding a new layer of security, we have just released new versions of all of the Firebase web SDKs to beta. These new SDKs allow you to import only what you need, reducing SDK size up to 80%, which can lead to less code and faster page loads. Download the new modularized SDKs today!
More Extensions for adding features and functionality
Firebase Extensions are pre-packaged bundles of code that automate common development tasks and let you add new functionality to your app in fewer steps. Now, we’re partnering with companies you know and trust so you can do even more. A few months ago, we worked with Stripe to launch the Run Subscription Payments with Stripe and the Send Invoices using Stripe extensions.
We’re pleased to announce new Extensions that help you implement search on Firestore with Algolia, send personalized emails to your customers with MailChimp, communicate with your users with MessageBird, and analyze user generated content with the Perspective API from Jigsaw, all without having to write any code or learn new APIs on your own. For more details, go to the Firebase Extensions page and install them today!
Our newest Extensions, built in partnership with other development teams, make it easy to integrate your app with the tools and services you love
Firebase products uncover actionable insights about your app, which you can use to deliver high-quality experiences to your users
Enhanced search, filtering, and games reporting in Crashlytics
Firebase Crashlytics gives you a complete view into your app’s stability so you can track, prioritize, and resolve bugs before they impact a large number of users. Many of you have instrumented Crashlytics custom keys as a way to gain more context about your app’s crashes. Now, you can find trends across these custom keys and filter down sessions to understand and fix your app’s trickiest crashes with Crashlytics’ new custom keys search and filtering capabilities.
You can now search and filter through custom keys in Crashlytics
Today, we’re also launching major improvements to Crashlytics to better meet the needs of game developers building natively or via popular game engines such as Unity and Cocos2d. These improvements include increased visibility into a crash’s root cause through more reliable and detailed NDK stack traces, superior grouping of Unity crashes, and by surfacing enhanced device metadata for Unity apps like GPU, DPI, Resolution, and more. This will help you ensure your players get a fun gaming experience that doesn’t abruptly crash.
Unveiling realtime data for Performance Monitoring and a revamped dashboard
High performance is key to user retention and engagement. Firebase Performance Monitoring gathers and presents data about your app’s performance, so you know exactly what’s happening in your app - and when users are experiencing slowness - from their point of view. Today, we’re excited to announce that Performance Monitoring now processes data in real time! This means you can closely watch your app’s performance during a release or while you’re launching a new feature, and then take action right away if issues arise.
Firebase Performance Monitoring now process data in realtime
A few months ago, we introduced you to the redesigned, customizable Performance Monitoring dashboard that allows you to bring the metrics you care about most to the forefront. Now, we’ve added a new traces table to this dashboard. The traces table helps you sort, search, and pinpoint the biggest performance changes that need your immediate attention - even if the changes occur in metrics you don’t monitor every day. The fully revamped Performance Monitoring dashboard with realtime data gives you a full picture of your app’s performance in one place. To get the new traces table with realtime data, simply update to the latest Performance Monitoring SDK.
The redesigned Performance Monitoring dashboard brings the metrics you care about most to the forefront
We’ve been working hard to strengthen Firebase Remote Config so as your app and business grow, you can tailor Firebase to suit your sophisticated needs.
Remote Config updates help you better visualize and optimize your app configuration
Firebase Remote Config lets you dynamically control and change your app so you can set up feature flags, run experiments to test ideas, and deliver personalized experiences, all without releasing a new version of your app. Over the past few months, we’ve made several improvements to help you better visualize your configuration and easily optimize your app to drive the outcomes you want - whether that’s increasing subscriptions like Tapple or Mobills, or boosting ad revenue like Pomelo Games.
First, we’ve redesigned the Remote Config console to highlight vital information and give you more flexibility. For example, we’ve increased the length of parameter descriptions, which means you have more space to describe what a parameter does, what values it can take, and whether or not it is safe to change. You can also expand or collapse parameters to see all of its conditional values in one view.
Second, we’ve updated the publish flow to make it crystal clear which of your changes are pending, and remind you to publish changes in your newly edited configuration.
Third, we’ve completely overhauled the Remote Config A/B test results page to remove unnecessary information and better organize the remaining data so you can act on your experiment results with confidence.
The updated A/B test results page makes it easier to understand how your experiments are performing
Last but not least, we’re putting the finishing touches on a new feature of Remote Config, called personalization. Personalization will give you the ability to automatically optimize individual user experiences to maximize the objectives you care about - such as revenue or engagement - through the power of machine learning. After a simple setup, personalization will continuously find and apply the right app configuration for each user to produce the best outcome, taking the load off of you. If you want an early look at this feature and to try it out for yourself, join our Alpha program.
With these improvements to Firebase, we aim to make app development faster, easier, and streamline your path to business success. People are relying on your apps to thrive in our new world, and you can rely on us to help you build, run, and scale your apps. Over the next few days, be sure to check out sessions, workshops, and more we have lined up for Google I/O 2021, and stay tuned for the rest of the year because we’ll have plenty more exciting announcements in the second half of 2021!
Hi, Firestore developers. We are pleased to announce that with the latest version of the client SDKs, you are able to use Firestore data bundles in your mobile and web applications! Data bundles can make certain types of Firestore applications much faster or less expensive.
That's great! Just one tiny little follow-up question: What are data bundles?
So essentially, data bundles are serialized groups of documents -- either individual documents, or a number of documents that you've retrieved using a specific query.
You can save these data bundles onto a CDN or your favorite object storage service, and then load them from your client applications. Once they've been loaded on to your client, your clients can read them in from your local cache like any other locally-cached Firestore data.
Well that just sounds like a database query with extra steps. Why would I want to do this?
The biggest reason is that by having your clients read common queries from a bundle on a CDN and then querying specifically against that cached data, you can avoid making extra calls against the Firestore database. If your application has a substantial number of users, this can lead to some cost savings, and could potentially be faster, too.
But to be clear, data bundles are an advanced feature and probably not something you should be considering until your application has a pretty sizable user base.
So what kinds of documents make sense to put into bundles?
The best kinds of bundles are ones where a majority of your users will be reading in all of the documents in that bundle, the number of documents is on the smaller side, and the contents of that data doesn't change too frequently.
Some good examples for this might be:
Data bundles are not good for:
I just had an idea: What if I were to stuff my entire database into a bundle, load that bundle onto my client, and then just query my entire database using only my cache?
That's a terrible idea.
Remember, the Firestore cache is not particularly fast when it comes to searching through large amounts of data. Overloading your cache by asking it to store a lot of documents that your users won't ever use is a good way of slowing your application to an unusable state. You should really only be leveraging data bundles to load up documents that most, if not all, of your users will be reading in.
Also, keep in mind that with bundles, you have to load in the entire bundle of documents when you load up a bundle, whereas with a normal document query, you're only downloading the documents that have changed from your local cache. So from a data usage perspective, stuffing too many documents into a bundle can be quite heavy.
Gotcha. So how would I implement these?
You can read the documentation for all the details, but in general, the process will work something like this:
So, once they're loaded, I can query them like normal data?
Yes. They'll be merged in with your locally cached data and you can make use of them like you would any other cached data. The data bundle also remembers the names of the queries you used to generate the bundle, so you can refer to these queries by name instead of re-creating them in code.
And how do I make sure I'm querying bundled data without incurring any additional Firestore costs?
The best way is to force your client to use the cached data. When you make a document request or database query, you're able to add an option like {source: 'cache'} that directs your client to only use the cached data, even if the network is available.
{source: 'cache'}
Tell me more about these "named queries" -- are these different from regular queries?
Not really -- the trick to using bundles effectively is that you want to make sure the query you're requesting on the client is exactly the same as the query that generated the bundle you've loaded. You could certainly do this in code, but by using a named query, you're ensuring that the client will always make the same query that generated the bundle in the first place. There's less room for error that way.
This also means that you can modify the server query that generates the bundle and, assuming you're still using the same name, the client will also use this new query without your needing to update any of the client code.
Notice that the version number has changed, but the client can continue to run the "seed-data" named query
What if I wanted to include data bundles alongside the rest of my local application data when I publish it to app stores? That way, if a user opens my app for the first time and is offline, I can read in the bundle and use that as starter data for my application.
Yes; that can be another great use of bundles. The process is the same, except you'll be reading in the bundle using a local call. Just be aware of the warnings above -- Firestore wasn't designed to be an "offline-first" database, so try to only load in as much data as you'll need to make sure your application is functional. If you overload your cache with too much information, you'll slow it down too much.
Okay, I think I'm ready to start using data bundles in my application.
Great! As always, feel free to ask questions on Stack Overflow if you need help, or reach out to us on the Cloud Firestore Discussion list if you have any other suggestions. Happy coding!
This article was originally published on the Google Play Medium channel.
Mobile games have evolved rapidly in recent years. Player expectations have increased along with this evolution. Players now demand games with rich and compelling stories that run smoothly regardless of their device. At the same time, as game studios realized the opportunities in going mobile, there is an ever-increasing number of mobile game titles competing for players' attention. In this increasingly competitive market, the ability to iterate and improve player experiences faster than rival titles is vital. Therefore, having the right tools and knowing how to apply them is a key skill for any game developer.
For many years, Firebase has provided game developers with the tools they need to build, release, and operate successful games. More than 2.5 million apps and games actively use Firebase every month, including global game studios such as Gameloft, Pomelo Games, and Halfbrick Studios.
This article explores four scenarios that game developers deal with on a daily basis and shows how Firebase provides the tools and insights to help you stay ahead of rivals.
It’s easier to provide better experiences to players when you understand how they interact with your game. Knowing how much time players spend in the game, what activities they prefer, and how often they come back enables you to personalize the game experience to suit their behavior and preferences. For example, different groups of players have different monetization preferences. Some may choose to spend money to improve their experience, while others may prefer to see ads and trade their time and attention instead. Understanding these differences – even details such as what people prefer to buy and what they do before making their first in-app purchase – is crucial to optimizing player experiences.
Firebase offers robust integration with Google Analytics. This integration helps shed light on who your players are and how they’re engaging with your game by providing insight into in-app events and user properties. This short video will show you how to log custom events and interpret the data to understand your players better.
Through the audiences feature, Firebase’s Google Analytics integration enables you to segment your user base in ways that are important to your business. You can use these custom audiences to filter reports to understand how different players engage with your game and identify patterns of behavior within the audience. Then, you can use this information to send targeted notifications and personalize the game behavior for player profiles. Take a look at this video to see how to set up audiences for your game.
Push notifications can be used for everything from reminders about opening a chest to letting everybody know the biggest update of the year is available. As push notifications allow real-time communication between a game company and its players, they’re often a critical part of a retention and re-engagement strategy. Most successful games have players worldwide, which means choosing just one language and time of day to communicate with them all is not ideal. After all, you don’t want to annoy players by sending them a push notification at 2 a.m.
Firebase Cloud Messaging lets game developers send targeted messages and notifications, which can be customized to suit your brand and align with player preferences. This video shows how you can send push notifications to players with devices set to a particular language and schedule delivery at an appropriate local time. Firebase Cloud Messaging also lets you target by game versions, geographies, your custom audiences, and many more variables. After sending the push notifications, you can see how many were delivered, how many were opened, and, if you choose to set it up, how many conversions happened.
While many players will gladly invest money in the games they enjoy, other players prefer ads in exchange for the gameplay. Many games employ a hybrid monetization strategy, meaning they include both ads and in-app purchases. As a general rule, the more ad impressions, the greater the revenue generated with ads. However, many other factors need to be considered to optimize and balance user experience and revenue. Differences between ad formats, their sizes, and how often they’re shown without disrupting the game experience are important factors.
Once you decide on these factors, how can you determine if the selected formats are the best ones? Is the frequency right or too much, and is the frequency negatively impacting retention? These questions can be answered quantitatively with Firebase A/B testing. A/B testing can be used with Firebase Remote Config to experiment with different combinations of ad types and frequencies to find the best option. To set up an experiment, all you need to do is define a goal, like increase total revenue, and identify secondary metrics such as D1 and D7 retention.
This video walks you through the process of setting up an experiment to test different ad formats so you can identify the best choice for a game. These parameters will vary from game to game, so it is always good to test the options available.
Pomelo Games, one of the top game studios in Uruguay, used Firebase Remote Config and Firebase A/B Testing to test the effect of showing interstitial ads to their entire player base versus a specific segment. Then, they used Google Analytics to measure the impact on revenue and retention. They also used Firebase Crashlytics to keep an eye on their game vitals. After two weeks of testing, the Pomelo team discovered that interstitial ads led to an average 25% increase in AdMob revenue and, surprisingly, a 35% increase in in-app purchases too. In both tests, there was almost no effect on retention. (Check out the full case study.)
Releasing new game features can be nerve-wracking because you may worry about how players will receive the new features. Will players enjoy the new feature you worked hard on? Will the new feature increase engagement and session time? One way to gain confidence that new features will positively impact your key metrics is by slowly rolling them out and seeing how they perform with a subset of your players before wider release.
In addition to gradually rolling out new features, it's also important to continually experiment with new content or in-game mechanics to optimize the player experience. However, constantly iterating your game can be a time-consuming and tedious process if you don't have the right tools.
Firebase Remote Config lets you dynamically configure your game and confidently roll out new features so you can deliver highly personalized experiences to your players without publishing an app update. This video shows you how to set up and tweak Remote Config parameters and instrument feature flagging.
Conclusion
Firebase is a powerful platform. It’s a great fit for game companies that want to enhance how they optimize experiences to delight their players and improve engagement and monetization. To get started with Firebase, you create your project in the Firebase console. To see more examples of how to use Firebase to supercharge your games business, check our Games with Firebase video series, where we walk through each step of the implementation process and share common use cases.
If you've ever built an app with Realtime Database you know that it's fast. When you combine the low-latency websocket connection with the local caching capabilities of the SDK, changes can feel pretty much instantaneous.
But have you ever wondered how fast your database operations are for your users in the real world? As a good app developer you need to collect real-world performance data to make sure that the experience of using your app in the real world matches your expectations! Many people in the tech industry call these field measurements Real User Monitoring (RUM) and they're considered the gold standard for measuring app performance and user experience. Firebase Performance Monitoring is a free and cross-platform service to help you collect and analyze RUM data for your app or website.
Firebase Performance Monitoring automatically measures common metrics like time to first paint and HTTP request performance. Because Realtime Database uses a long-running WebSocket connection rather than separate HTTP requests we'll need to use Custom Traces to monitor the performance of our database operations.
For this post we built a Firebase-powered implementation of the standard TodoMVC app in React using the ReactFire library:
Each time we add, update, or remove an item in our to-do list we're making a change in Realtime Database directly. For example here's the code to add a new todo item:
function App() { // Get an instance of Firebase Realtime Database using the 'reactfire' library const db = useDatabase(); // Load all the 'todos' from the database const todosRef = db.ref("todos"); const list = useDatabaseList(todosRef); // ... // Add a new todo to the database const handleAddTodo = (text) => { todosRef.push({ text, completed: false, }); }; // ... }
This operation appears to be instantaneous because the Realtime Database SDK immediately adds the new todo to the local listener while it waits for the backend to acknowledge, or reject, the write. But what if we want to find out how long it actually takes to commit the write on the server?
Let's add some code to measure how long this really takes. We'll create a new function called tracePromise to help us log a custom trace for any action which returns a Promise and then we'll add a simple custom trace called add-todo.
tracePromise
Promise
add-todo
function tracePromise(trace, promise) { trace.start(); promise.then(() => trace.stop()).catch(() => trace.stop()); } function App() { // Get and instance of Performance Monitoring using the 'reactfire' library const perf = usePerformance(); // ... const handleAddTodo = (text) => { const p = todosRef.push({ text, completed: false, }); // Use the 'tracePromise' helper to see how long this takes const trace = perf.trace("add-todo"); tracePromise(trace, p); }; // ... }
If we deploy this code and head to the Firebase console we can see that the "add-todo" operation takes about 100ms in most cases, with 160ms being the worst case.
If we break this down by country we can see that the operation is much faster for users in the US than in other countries:
This makes sense! Most Realtime Database instances are located in the United States, which can have an impact on latency for users around the world. Geographic latency increases can depend on physical distances as well as the network topology between two points.
We don't often think about it when coding but data can only travel at the speed of light! For two points on opposite sides of the earth the speed of light alone adds 66ms of latency, and that's not including any of the actual network or processing latency along the way. This is why adding RUM to your app is so critical.
Well, the good news is that Realtime Database is now expanding to more regions around the world, beginning with the launch of our Belgium region in late 2020. A todo list app lends itself really well to sharding because each user's data is exclusively their own. So let's add a second Realtime Database instance to our app in the Belgium region, and assign each user to a random database instance to see what effect that has on our latency:
First we'll add a custom attribute to our Performance Monitoring traces so that we can filter the data by location later:
function getMyLocationCode() { // User's location could be stored in a URL param, cookie, localStorage, etc. // ... } function tracePromise(trace, promise) { // Add a custom attribute to the trace before starting it const location = getMyLocationCode(); trace.putAttribute("location", location); trace.start(); promise.then(() => trace.stop()).catch(() => trace.stop()); }
Now let's deploy these changes and wait for new user data to come in. After a few days we can see that our experiment worked! First we can see that our distribution now has two obvious peaks:
This is what we expected, because we're now randomly assigning users to one of two database instances. Depending on the one they get, it will either be close to them or far away.
If we look into the data more, we can see that our German users have a really fast connection to the Belgium instance! They're getting updates in as little as 22ms. That's a huge improvement over the 150ms+ they were getting when communicating with an instance in the US. While the local caching in the Firebase SDK will make the UI feel snappy either way, this will make a huge difference in the speed of collaborative or multi-device scenarios.
With this RUM data in hand we can be confident that adding a new database region can make our app faster. Next we'll need to find a way to detect the user location when they sign up and assign each account to the best region for them. For now we'll leave that as an exercise for the reader!
If you're ready to get started measuring performance in your own app, check out these links:
Version 7.1.0 of the Firebase Unity and C++ SDKs did a lot to improve Firebase Remote Config and better aligned it with the iOS and Android SDKs. In the process, however, there were some minor changes to the API that may require some action on your part.
First, in the Unity/C# SDK, the static methods you’ve been using have been removed from FirebaseRemoteConfig and moved into FirebaseRemoteConfigDeprecated. For technical reasons, we could not deprecate these functions and leave them in place. If you want a fast and easy way to update Firebase in your game, change FirebaseRemoteConfig to FirebaseRemoteConfigDeprecated. This will let your existing code work without any additional changes, but you won't be able to take advantage of the newer features.
FirebaseRemoteConfig
FirebaseRemoteConfigDeprecated
Also worth noting is that IsDeveloperMode no longer has any effect and can be omitted. You likely paired this with a change to MinimumFetchInterfaclInMilliseconds or by passing a TimeSpan into FetchAsync when debugging Remote Config. Shorter fetch intervals now function without IsDeveloperMode making RemoteConfig an even stronger tool in your LiveOps toolbox!
IsDeveloperMode
MinimumFetchInterfaclInMilliseconds
TimeSpan
FetchAsync
C++ developers can leave their code as is, although you will be warned about deprecation.
Developers wishing to future proof their code and take advantage of new features as they become available should switch to using a Remote Config instance rather than using static functions.
Unity/C#
var remoteConfig = FirebaseRemoteConfig.DefaultInstance;
C++
auto remoteConfig = ::firebase::remote_config::RemoteConfig::GetInstance(app);
SetDefaults is now asynchronous. This is probably a good thing for game developers hoping to move logic off of the main thread, but you do have to be a little more cautious when building your app logic.
remoteConfig.SetDefaultsAsync(new Dictionary<string, object> { {"starting_player_lives", 3}, {"theme", "dark"} }).ContinueWithOnMainThread(task => { // it's now safe to Fetch });
std::vector<remote_config::ConfigKeyValueVariant> defaultConfig = { {"starting_player_lives", 3}, {"theme", "dark"}, }; remoteConfig->SetDefaults(defaultConfig.data(), defaultConfig.size()) .OnCompletion([](const ::firebase::Future<void>&){ // it's now safe to Fetch });
It’s now possible to Fetch and Activate Remote Config changes in a single call.
remoteConfig.FetchAndActivateAsync().ContinueWithOnMainThread(task => { // handle completion });
remoteConfig->FetchAndActivate().OnCompletion([](const ::firebase::Future<bool>& future) { // handle completion });
And when you are ready to read your configuration, it’s now possible to retrieve all of the keys and values in a single language-specific native collection. No more getting a list of keys and looking up each value individually!
IDictionary<string, ConfigValue> values = remoteConfig.AllValues;
std::map<std::string, ::firebase::Variant> values = remoteConfig->GetAll();
Finally, if you would like to debug your Remote Config settings, you may want to reduce the interval between fetches.
var configSettings = new ConfigSettings(); if (Debug.isDebugBuild) { // refresh immediately when debugging configSettings.MinimumFetchInternalInMilliseconds = 0; } FirebaseRemoteConfig.DefaultInstance.SetConfigSettingsAsync(configSettings).ContinueWithOnMainThread(task => { // handle completion });
::firebase::remote_config::ConfigSettings settings; settings.minimum_fetch_interval_in_milliseconds = 0; // caution, only do this in debug mode! remoteConfig->SetConfigSettings(settings);
These changes are part of an ongoing effort to improve Remote Config, including some exciting new features you'll be hearing about in the future. Updating your games now will ensure that you can continue to take the advantage of the latest advances in Remote Config.