Firebase Security Rules gate your user's access to and enforce validations for Firestore, Firebase Storage, and the Realtime Database. It's important to code review the Security Rules, just like you code review the application code. Because these rules are written in a domain-specific language, that puts some people in the position of code reviewing something they don't feel like they understand.
If you're finding yourself in that position, don't worry! This post will walk through how to approach reviewing and giving good feedback on Security Rules. The examples will be from Firestore Security Rules, and are mostly applicable to Storage as well. If you're reviewing Realtime Database Security Rules, although these principles apply, the rules use a different language, so the examples will be different.
When you're looking at Security Rules, check first for any top level rules that apply to everything. A document can match multiple rules, and if any rule grants access, access is granted. In the example below, there's a specific rule that only grants authors access to post documents, but the global rule lets anyone on the internet read or write to any place in your database:
post
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if true; } match /posts/{post} { allow read, write: if request.resource.data.authorUID == request.auth.uid ; } } }
It's important to look for the global match statement match /{document=**} throughout the entire rules file, not just at the top. If there are thorough rules but also a global match statement, universal access will still be granted through the global match statement.
match /{document=**}
There are a very small number of valid use cases for global match statements. For example, granting access to admin users:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if isAdmin(); } } }
If you find a global rule that is read, write: if true, you can stop your review and ask them to fix it. If you find any other condition on a global rule, make sure it makes sense for your application.
read, write: if true
The next thing to do is to look at the data that you're storing. What is Personally Identifiable Information (PII) that should only be accessed by that particular user?
Security Rules apply to entire documents, not just fields. You should be able to look at each kind of document that you have and describe which kind of users should be able to read it, create it, update it, and delete it.
If you find documents where it's fine for most of the document to be read by anyone, but a few fields need to remain private, break those fields into their own document; the easiest way to do this is usually to create a subcollection off the existing document.
Now check the Security Rules for each of the documents that you identified as containing PII. The best practice for PII is that it is keyed by the user's ID, and only that user is allowed access:
match /secrets/{uid} { allow create, update: if request.auth.uid == uid; }
This pattern only works if there's a max of one document in the collection for each user. For cases of multiple documents per user, you could create subcollections of a user document:
match /users/{uid}/secrets/{secret} { allow create, update: if request.auth.uid == uid; }
Or you could include the id of the user who should have access as an attribute, and restrict access to that user:
match /secrets/{secret} { allow create, update: if request.auth.uid == request.resource.data.uid; }
Ideally, you would check that each document is as locked down as possible, but if you have limited time, the most important thing to check is that PII lives in separate documents and those PII documents are only accessible to that user.
Just like application changes should come with test changes, so should Security Rules. Security Rules tests run against the Firebase Emulator Suite, and can be included in your CI setup.
If you're not yet testing Security Rules, check out this documentation to get started, this video for an overview of testing, and this blog post and video on adding your tests to CI.
If the Security Rules are fully tested, there should be a lot of tests. For each kind of document, there are usually four different kinds of access: read, create, update, and delete. (These are just the most common permissions to grant; create, update, and delete can be rolled up into write, and read can be broken into get and list.) For each permission, there should be a test of the happy path, granting permission, and a test for each situation that should deny access.
read
create
update
delete
write
get
list
Say I have one rule:
// firestore.rules allow update: if // User is the author resource.data.authorUID == request.auth.uid && // `authorUID` and `createdAt` are unchanged request.resource.data.diff(request.resource.data).unchangedKeys().hasAll([ "authorUID", "createdAt" ]) && // Title must be < 50 characters long request.resource.data.title.size < 50;
To completely test this, I would write tests around granting access and each way that access could be denied:
// test.js const firebase = require("@firebase/rules-unit-testing"); const dbAuthorAuth = firebase.initializeTestApp({ projectId: TEST_FIREBASE_PROJECT_ID, auth: { uid: "author", email: "alice@example.com" } }).firestore(); const dbOtherAuth = firebase.initializeTestApp({ projectId: TEST_FIREBASE_PROJECT_ID, auth: { uid: "other", email: "otto@example.com" } }).firestore(); describe("blog posts", () => { before(async () => { dbAuthorAuth.doc("drafts/12345").set({ authorUID: "author", createdAt: Date.now(), title: "Make an apple", content: "TODO!" }); }); it("can be updated by author if immutable fields are unchanged", async () => { await firebase.assertSucceeds(dbAuthorAuth.doc("drafts/12345").update({ title: "Make an app", content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." })); }); it("cannot be updated by anyone other than the author", async () => { await firebase.assertFails(dbOtherAuth.doc("drafts/12345").update({ title: "Make an app", content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." })); }); it("cannot be updated by author if the author ID is changed", async () => { await firebase.assertFails(authorDb.doc("drafts/12345").update({ authorUID: "New Person" title: "Make an app", content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." })); }); it("cannot be updated by author if the created date is changed", async () => { await firebase.assertFails(authorDb.doc("drafts/12345").update({ createdAt: Date.now(), title: "Make an app", content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." })); }); it("cannot be updated if the title is over 50 characters", async () => { await firebase.assertFails(authorDb.doc("drafts/12345").update({ title: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." })); });
As the reviewer, look through their test cases, and make sure they have tested each kind of document. If they've written good test descriptions, that's the easiest place to understand what the Security Rules are doing. Similarly, if they've written code comments in their rules, that can also be a good entry point to understanding the Security Rules.
Subcollections don't inherit the rules from the parent document, so make sure they're specifically covered in the Security Rules. Look at the subcollections you're storing in Firestore; if all documents should have the same access that a parent document has, then that parent document should use the glob syntax: match /post/{id=**}.
match /post/{id=**}
What's more common is that a subcollection has been broken out into a subcollection because a different person needs to read it, or someone else is allowed to write to it. In that case, check the Security Rules to make sure it has its own match statement. Nesting is only a stylistic difference; whether you nest your match statements or not, make sure this is a match statement for the documents in the subcollections:
// Nested match statements are fine match /post/{postID} { allow read: if ... match /comments/{commentID} { allow read: if ... } } // Unnested match statements are fine match /post/{postID} { allow read: if ... } match /comments/{commentID} { allow read: if ... }
If you're reviewing Realtime Database Security Rules, child nodes inherit from parent nodes, the opposite of the behavior in Firestore.
Security Rules can enforce type and data validations for specific fields in addition to preventing unwanted access. If you know that some documents have required fields, immutable fields, fields that must be a timestamp, or a field that must contain data in a specific range, check that those are enforced in the Security Rules for those documents. For example, in this rule, I'm checking that the immutable fields of authorUID, publishedAt, and url aren't changed by an update, and that the required fields of content, title, and visible are still present:
authorUID
publishedAt
url
content
title
visible
allow update: if // Immutable fields are unchanged request.resource.data.diff(request.resource.data).unchangedKeys().hasAll([ "authorUID", "publishedAt", "url" ]) && // Required fields are present request.resource.data.keys().hasAll([ "content", "title", "visible" ]);
If you use the more granular permissions of create, update, and delete in place of write, make sure that validations apply to both create and update.
Because the Admin SDK authorizes using service account credentials, all requests from the Admin SDK, including Cloud Functions for Firebase, bypass Security Rules. To give a thorough security review for a Firebase app, it's also necessary to look at any other writes that are happening to your backend via the Admin SDK.
For example, if I have great Firestore Security Rules, but a Cloud Function exports data to a storage bucket that has no Security Rules, that would be a terrible way to treat my user's data. The flip side of this is that Cloud Functions can be used in situations where Security Rules don't work, for example, returning individual fields from documents. See this blog post for tips to use Cloud Functions in conjunction with Security Rules.
If you're using Cloud Firestore or Cloud Storage for Firebase, you're also using Security Rules. (If you're using the default rules instead of tailoring them to your app, this is where to start!) We're excited to announce that in the last few months we've released some substantial improvements to the tools for writing and debugging Rules, improvements to the Rules language itself, and increases to the size limits for Rules!. These are a few of the great new features. Check out the Security Rules Release Notes for a comprehensive list of everything we've released.
We've released several improvements to make the rules language more expressive and succinct. One particularly verbose pattern was comparing the new values of a document to existing values. The new Set type available in Rules is purpose-built for these comparisons, and also has methods for functionality you'd expect for a Set, like getting the intersection, union, or difference between Sets. For example:
Set type
Allow a user to create a document if the document has required and optional fields, but not others:
allow create: if (request.resource.data.keys().toSet() .hasOnly(["required","and","optional","keys"])
Sets come with == and in operators and hasAll, hasAny, hasOnly, difference, intersection, union, and size methods.
==
in
hasAll
hasAny
hasOnly
difference
intersection
union
size
Sets are most useful in conjunction with the Map class, and because the request and resource objects are both structured as maps, you're probably already familiar with it. Map recently got a few new methods, diff and get, that will hopefully open the door to more concise rules for everyone. Here's how they work:
Map
request
resource
diff
Map.diff() is called on one map, and takes the second map as an argument: map1.diff(map2). It returns a MapDiff object, and all of the MapDiff methods, like addedKeys, changedKeys, or affectedKeys return a Set object.
map1.diff(map2)
addedKeys
changedKeys
affectedKeys
Set
Map.diff() can solve some verbose patterns like checking which fields changed before and after a request. For example, this rule allows an update if the "maxLevel" field was the only field changed:
allow update: if request.resource.data.diff(resource.data).changedKeys().hasOnly(["maxLevel"]);
In the next example, posts have a field indicating the user role required to modify the post. We'll use Map.get() to get the "roleToEdit" field. If the document doesn't have the field, it will default to the "admin" role. Then we'll compare that to the role that's on the user's custom claims:
"roleToEdit"
"admin"
allow update, delete: if resource.data.get("roleToEdit", "admin") == request.auth.token.role;
Keep in mind that because Sets are not ordered but Lists are. You can convert a List to a Set, but you can't convert a Set to a List.
Local variables have been one of the most requested features in Rules, and they're now available within functions. You can declare a variable using the keyword let, and you can have up to 10 local variables per function.
let
Say you're commonly checking that a user meets the same three conditions before granting access: that they're an owner of the product or an admin user, that they successfully answered a challenge question, and that they meet the karma threshold.
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /products/{product} { allow read: if true; allow write: if (exists(/databases/$(database)/documents/admins/$(request.auth.uid)) || exists(/databases/$(database)/documents/product/owner/$(request.auth.uid))) && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.passChallenge == true && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.karma > 5; } match /categories/{category} { allow read: if true; allow write: if (exists(/databases/$(database)/documents/admins/$(request.auth.uid)) || exists(/databases/$(database)/documents/product/owner/$(request.auth.uid))) && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.passChallenge == true && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.karma > 5; } match /brands/{brand} { allow read, write: if (exists(/databases/$(database)/documents/admins/$(request.auth.uid)) || exists(/databases/$(database)/documents/product/owner/$(request.auth.uid))) && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.passChallenge == true && get(/databases/$(database)/documents/users/$(request.auth.uid)) .data.karma > 5; } } }
Those conditions, along with the paths I'm using for lookups can all now become variables in a function, which creates more readable rules:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { function privilegedAccess(uid, product) { let adminDatabasePath = /databases/$(database)/documents/admins/$(uid); let userDatabasePath = /databases/$(database)/documents/users/$(uid); let ownerDatabasePath = /databases/$(database)/documents/$(product)/owner/$(uid); let isOwnerOrAdmin = exists(adminDatabasePath) || exists(ownerDatabasePath); let meetsChallenge = get(userDatabasePath).data.get("passChallenge", false) == true; let meetsKarmaThreshold = get(userDatabasePath).data.get("karma", 1) > 5; return isOwnerOrAdmin && meetsChallenge && meetsKarmaThreshold; } match /products/{product} { allow read: if true; allow write: if privilegedAccess(); } match /categories/{category} { allow read: if true; allow write: if privilegedAccess(); } match /brands/{brand} { allow read, write: if privilegedAccess(); } } }
You can see at a glance that the same conditions grant access to write to documents in the three different collections.
The updated version also uses map.get() to fetch the karma and passChallenge fields from the user data, which helps keep the new function concise. In this example, if there is no karma field for a user, then the get returns false. Keep in mind that Map.get() fetches a specific field, and is separate from the DocumentReference.get() that fetches a document.
map.get()
karma
passChallenge
Map.get()
DocumentReference.get()
This is the first time we've introduced an if/else control flow, and we hope it will make rules smoother and more powerful.
if/else
Here's an example of using a ternary operator to specify complex conditions for a write. A user can update a document in two cases: first, if they're an admin user, they need to either set the field overrideReason or approvedBy. Second, if they're not an admin user, then the update must include all the required fields:
overrideReason
approvedBy
allow update: if isAdminUser(request.auth.uid) ? request.resource.data.keys().toSet().hasAny(["overrideReason", "approvedBy"]) : request.resource.data.keys().toSet().hasAll(["all", "the", "required", "fields"])
It was possible to express this before the ternary, but this is a much more concise expression.
And finally, here's a feature for those of you with longer rules. Until now, rules files had to be smaller than 64 KB. (To be more specific, the compiled AST of the rules file had to be smaller than 64 KB, and you wouldn't know you were within the limit until you tried to deploy the rules.) This limit was holding some developers back, and once you reached the limit, you had to start making tradeoffs in your rules. We definitely wanted to fix this.
Since this is one of the limits that helps rules return a decision in nanoseconds, we wanted to find a way to increase the limit without sacrificing performance. We optimized how we compile and store the Rules file, and we were able to quadruple the limit to 256 KB!
The limits on rules are in place to keep rules fast enough to return a decision in nanoseconds, but we work hard to keep them workable. Let us know if you start to outgrow any of them
All of these features are informed by the feedback we hear from you about what's great, what's hard, and what's confusing about Firestore Security Rules, so keep letting us know what you think!
At Firebase, we're committed to transparency and a thriving developer community, which is why we started open sourcing our SDKs last year. Today, we're continuing on that mission by open sourcing our first Firebase Android SDKs.
For this initial release, we are open sourcing our Cloud Firestore, Cloud Functions, Realtime Database, Storage, and FirebaseCommon SDKs. We intend to release more SDKs going forward, so don't forget to star or watch the repo.
The Firebase Android SDK source code can be found at https://github.com/firebase/firebase-android-sdk.
For the SDKs included in the repository, GitHub is the source of truth, though you can also find our project in the Google Open Source directory and on firebaseopensource.com. On GitHub, you'll be able to observe the progress of new features and bug fixes and build a local copy of the SDK on your development machine to preview upcoming releases. Our GitHub README provides more details on how you build, test, and contribute to our Android SDK.
As with our already available open-source iOS, Javascript, Node.js, Java, Python, Go and .NET SDKs, should you find issues in our code you can report them through the standard GitHub issue tracker. Your feedback is vital in shaping the future of Firebase and we look forward to hearing from you on GitHub!
For most developers, building an authentication system for your app can feel a lot like paying taxes. They are both relatively hard to understand tasks that you have no choice but doing, and could have big consequences if you get them wrong. No one ever started a company to pay taxes and no one ever built an app just so they could create a great login system. They just seem to be inescapable costs.
But now, you can at least free yourself from the auth tax. With Firebase Authentication, you can outsource your entire authentication system to Firebase so that you can concentrate on building great features for your app. Firebase Authentication makes it easier to get your users signed-in without having to understand the complexities behind implementing your own authentication system. It offers a straightforward getting started experience, optional UX components designed to minimize user friction, and is built on open standards and backed by Google infrastructure.
Implementing Firebase Authentication is relatively fast and easy. From the Firebase console, just choose from the popular login methods that you want to offer (like Facebook, Google, Twitter and email/password) and then add the Firebase SDK to your app. Your app will then be able to connect securely with the real time database, Firebase storage or to your own custom back end. If you have an auth system already, you can use Firebase Authentication as a bridge to other Firebase features.
Firebase Authentication also includes an open source UI library that streamlines building the many auth flows required to give your users a good experience. Password resets, account linking, and login hints that reduce the cognitive load around multiple login choices - they are all pre-built with Firebase Authentication UI. These flows are based on years of UX research optimizing the sign-in and sign-up journeys on Google, Youtube and Android. It includes Smart Lock for Passwords on Android, which has led to significant improvements in sign-in conversion for many apps. And because Firebase UI is open source, the interface is fully customizable so it feels like a completely natural part of your app. If you prefer, you are also free to create your own UI from scratch using our client APIs.
And Firebase Authentication is built around openness and security. It leverages OAuth 2.0 and OpenID Connect, industry standards designed for security, interoperability, and portability. Members of the Firebase Authentication team helped design these protocols and used their expertise to weave in latest security practices like ID tokens, revocable sessions, and native app anti-spoofing measures to make your app easier to use and avoid many common security problems. And code is independently reviewed by the Google Security team and the service is protected in Google’s infrastructure.
Fabulous uses Firebase Authentication to power their login system. Fabulous is a research-based app incubated in Duke University’s Center for Advanced Hindsight. Its goal is to help users to embark on a journey to reset poor habits, replacing them with healthy rituals, with the ultimate goal of improving health and well-being.
The developers of Fabulous wanted to implement an onboarding flow that was easy to use, required minimal updates, and reduced friction with the end user. They wanted an anonymous option so that users could experiment with it before signing up. They also wanted to support multiple login types, and have an option where the user sign-in flow was consistent with the look and feel of the app.
“I was able to implement auth in a single afternoon. I remember that I spent weeks before creating my own solution that I had to update each time the providers changed their API” - Amine Laadhari, Fabulous CTO.
Chu-Day is an application (available on Android and iOS) that helps couples to never forget the dates that matter most to them. It was created by the Korean firm Malang Studio, that develops character-centric, gamified lifestyle applications.
Generally, countdown and anniversary apps do not require users to sign-in, but Malang Studio wanted to make Chu-day special, and differentiate it from others by offering the ability to connect couples so they could jointly countdown to a special anniversary date. This required a sign-in feature, and in order to prevent users from dropping out, Chu-day needed to make the sign-in process seamless.
Malang Studio was able to integrate an onboarding flow in for their apps, using Facebook and Google Sign-in, in one day, without having to worry about server deployment or databases. In addition, Malang Studio has also been taking advantage of the Firebase User Management Console, which helped them develop and test their sign-in implementation as well as manage their users:
“Firebase Authentication required minimum configuration so implementing social account signup was easy and fast. User management feature provided in the console was excellent and we could easily implement our user auth system.” - Marc Yeongho Kim, CEO / Founder from Malang Studio
For more about Firebase Authentication, visit the developers site and watch our I/O 2016 session, “Best practices for a great sign-in experience.”
Eighteen months ago, Firebase joined Google. Since then, our backend-as-a-service (BaaS) that handles the heavy lifting of building an app has grown from a passionate community of 110,000 developers to over 450,000.
Our current features -- Realtime Database, User Authentication, and Hosting -- make app development easier, but there’s more we can do, so today, we’re announcing a major expansion!
Firebase is expanding to become a unified app platform for Android, iOS and mobile web development. We’re adding new tools to help you develop faster, improve app quality, acquire and engage users, and monetize apps. On top of this, we’re launching a brand new analytics product that ties everything together, all while staying true to the guiding principles we’ve had from the beginning:
Firebase Analytics is our brand new, free and unlimited analytics solution for mobile apps. It benefits from Google’s experience with Google Analytics, and features some new capabilities for apps:
Firebase Analytics is user and event-centric and gives you insight into what your users are doing in your app. You can also see how your paid advertising campaigns are performing with cross-network attribution, which tells you where your users are coming from. You can see all of this from a single dashboard.
Firebase Analytics is also integrated with other Firebase offerings to provide a single source of truth for in-app activity and through a feature called Audiences. Audiences let you define groups of users with common attributes. Once defined, these groups can be accessed from other Firebase features -- to illustrate, we’ll reference Audiences throughout this post.
To help you build better apps, our suite of backend services is expanding.
Google Cloud Messaging, the most popular cloud-to-device push messaging service in the world, is integrating with Firebase and changing its name to Firebase Cloud Messaging (FCM). Available for free and for unlimited usage, FCM supports messaging on iOS, Android, and the Web, and is heavily optimized for reliability and battery-efficiency. It’s built for scale and already sends 170 billion messages per day to two billion devices.
One of our most requested features is the ability to store images, videos, and other large files. We’re launching Firebase Storage so developers can easily and securely upload and download such files. Firebase Storage is powered by Google Cloud Storage, giving it massive scalability and allowing stored files to be easily accessed by Google Cloud projects. The Firebase Storage client SDKs have advanced logic to gracefully handle poor network conditions.
Firebase Remote Config gives you instantly-updatable variables that you can use to tune and customize your app on the fly to deliver the best experience to your users. You can enable or disable features or change the look and feel without having to publish a new version. You can also target configurations to specific Firebase Analytics Audiences so that each of your users has an experience that’s tailored for them.
In addition, we’re continuing to invest heavily in our existing backend products, Firebase Realtime Database, Firebase Hosting, and Firebase Authentication. Authentication has seen the biggest updates, with brand new SDKs, and an upgraded backend infrastructure. This provides added security, reliability, and scale using the same technologies that power Google’s own accounts. We’ve also added new Authentication features including email verification and account linking. For Hosting, custom domain support is now free for all developers, and the Database has a completely rebuilt UI. We’re working hard on other great Realtime Database features, stay tuned for those.
We’re adding two new offerings to Firebase to help you deliver higher quality apps.
When your app crashes, it’s bad for your users and it hurts your business. Firebase Crash Reporting gives you prioritized, actionable reports to help you diagnose and fix problems in your iOS or Android app after it has shipped. We’ve also connected Crash Reporting to Audiences in Firebase Analytics, so you can tell if users on a particular device, in a specific geography, or in any other custom segment are experiencing elevated crash rates.
Cloud Test Lab, announced last year at Google I/O, is now Firebase Test Lab for Android. Test Lab helps you find problems in your app before your users do. It allows for both automatic and customized testing of your app on real devices hosted in Google data centers.
After you’ve launched your app, we can help you grow and re-engage users with five powerful growth features.
Firebase Notifications is a new UI built on top of the Firebase Cloud Messaging APIs that lets you easily deliver notifications to your users without writing a line of code. Using the Notifications console you can re-engage users, run marketing campaigns, and target messages to Audiences in Firebase Analytics.
Firebase Dynamic Links make URLs more powerful in two ways. First, they provide “durability” -- links persist across the app install process so users are taken to the right place when they first open your app. This “warm welcome” increases engagement and retention. Second, they allow for dynamically changing the destination of a link based on run-time conditions, such as the type of browser or device. Use them in web, email, social media, and physical promotions to gain insight into your growth channels.
Firebase Invites turns your customers into advocates. Your users can easily share referral codes or their favorite content via SMS or email to their network, so you can increase your app's reach and retention.
Firebase App Indexing, formerly Google App Indexing, brings new and existing users to your app from the billions of Google searches. If your app is already installed, users can launch it directly from the search results. New users are presented with a link to install your app.
AdWords, Google’s advertising platform for user acquisition and engagement, is now integrated with Firebase. Firebase can track your AdWords app installs and report lifetime value to the Firebase Analytics dashboard. Firebase Audiences can be used in AdWords to re-engage specific groups of users. In-app events can be defined as conversions in AdWords, to automatically optimize your ads, including universal app campaigns.
To help you generate revenue from your app and build a sustainable business, we’ve integrated Firebase with AdMob, an advertising platform used by more than 1 million apps. We’ve made it easier to get started with AdMob when you integrate the Firebase SDK into your app. Using AdMob, you can choose from the latest ad formats, including native ads, which help provide a great user experience.
Along with new feature launches, we’re moving our website and documentation to a new home: firebase.google.com.
We’re also launching a brand new console to manage your app. It is completely redesigned and rebuilt for improved ease of use, and we’ve deeply integrated it with other Google offerings, like Google Cloud and Google Play.
Firebase now uses the same underlying account system as Google Cloud Platform, which means you can use Cloud products with your Firebase app. For example, a feature of Firebase Analytics is the ability to export your raw analytics data to BigQuery for advanced querying. We’ll continue to weave together Cloud and Firebase, giving you the functionality of a full public cloud as you grow.
You can also link your Firebase account to Google Play from our new console. This allows data, like in-app purchases, to flow to Firebase Analytics, and ANRs (application not responding) to flow to Firebase Crash Reporting, giving you one place to check the status of your app.
Finally, we’re announcing the beta launch of a new C++ SDK. You can find the documentation and getting started guides here.
We’re excited to announce that most of these new products, including Analytics, Crash Reporting, Remote Config, and Dynamic Links, are free for unlimited usage.
For our four paid products: Test Lab, Storage, Realtime Database, and Hosting, we’re announcing simpler pricing. We now offer:
Many things are changing, but Firebase’s core principles remain the same. We care deeply about providing a great developer experience through easy-to-use APIs, intuitive interfaces, comprehensive documentation, and tight integrations. We’re committed to cross-platform development for iOS, Android, and the Web, and when you run into trouble, we’ll provide support to help you succeed.
If you were using a Firebase feature before today -- like the Realtime Database, GCM, or App Indexing -- there’s no impact on your app. We’ll continue to support you, though we recommend upgrading to the latest SDK to access our new features.
As far as we’ve come, this is still early days. We’ll continue to refine and add to Firebase. For example, the JavaScript SDK does not yet support all the new features. We’re working quickly to close gaps, and we’d love to hear your feedback so we can improve. You can help by requesting a feature.
All the new features are ready-to-go, and already in use by apps like Shazam, SkyScanner, PicCollage, and more. Get started today by signing up, visiting our new site, or reading the documentation to learn more.
We can’t wait to hear what you think!