Three years ago, we launched Firebase Hosting to make it easier for developers to deliver fast, engaging experiences on the web. Two months ago, we launched the beta of Cloud Functions for Firebase to let developers write custom backend logic without having to worry about servers or infrastructure. More recently at Google I/O, we brought Firebase Hosting and Cloud Functions together to provide a flexible set of tools to build Progressive Web Apps with world-class scale and performance.
You can connect an HTTPS Cloud Function to your Firebase Hosting app by adding a rewrite to the firebase.json configuration for your project:
firebase.json
{ "hosting": { "rewrites": [ {"source": "/function/**", "function":"myFunction"} ] } }
Once connected, matching requests seamlessly proxy to your Cloud Function (in the example above, a function named myFunction). This one-line change enables exciting new capabilities for Firebase Hosting users including:
myFunction
For Cloud Functions users, you can now run functions on an SSL-secured custom domain and get powerful caching to avoid unnecessary executions.
To get started using Cloud Functions on Firebase Hosting for your own Firebase project, take a look at our documentation. You can also learn more in our I/O session: Building Fast Web Experiences with Firebase Hosting.
In apps that allow users to post public content - for instance in forums, social networks and blogging platforms - there is always a risk that inappropriate content could get published. In this post, we'll look at ways you can automatically moderate offensive content in your Firebase app using Cloud Functions.
The most commonly used strategy to moderate content is "reactive moderation". Typically, you'll add a link allowing users to report inappropriate content so that you can manually review and take down the content that does comply with your house rules. You can better prevent offensive content from being publicly visible and complement your reactive moderation by adding automated moderation mechanisms. Let's see how you can easily add automatic checks for offensive content in text and photos published by users on your Firebase apps using Cloud Functions.
We'll perform two types of automatic content moderation:
Text moderation where we'll remove swearwords and all shouting (e.g. "SHOUTING!!!").
Image moderation where we'll blur images that contain either adult or violent content.
Automatic moderation, by nature, needs to be performed in a trusted environment (i.e. not on the client), so Cloud Functions for Firebase is a great, natural fit for this. Two functions will be needed to perform the two types of moderation.
The text moderation will be performed by a Firebase Realtime Database triggered function named moderator. When a user adds a new comment or post to the Realtime Database, a function is triggered which uses the bad-words npm package to remove swear words.We'll then use the capitalize-sentence npm package to fix the case of messages that contain too many uppercase letters (which typically meaning users are shouting). The final step will be to write back the moderated message to the Realtime Database.
moderator
To illustrate this we'll use a simple data structure that represents a list of messages that have been written by users of a chat room. These are made of an object with a text attribute that gets added to the /messages list:
text
/messages
/functions-project-12345 /messages /key-123456 text: "This is my first message!" /key-123457 text: "IN THIS MESSAGE I AM SHOUTING!!!"
Once the function has run on the newly added messages, we'll add two attributes: sanitized which is true when message has been verified by our moderation function and moderated which is true if it was detected that the message contained offensive content and was modified. For instance, after the function runs on the two sample messages above we should get:
sanitized
true
moderated
/functions-project-12345 /messages /key-123456 text: "This is my first message!", sanitized: true, moderated: false /key-123457 text: "In this message I am shouting." sanitized: true, moderated: true
Our moderator function will be triggered every time there is a write to one of the messages. We set this up by using the functions.database().path('/messages/{messageId}').onWrite(...) trigger rule. We'll moderate the message and write back the moderated message into the Realtime Database:
functions.database().path('/messages/{messageId}').onWrite(...)
exports.moderator = functions.database.ref('/messages/{messageId}') .onWrite(event => { const message = event.data.val(); if (message && !message.sanitized) { // Retrieved the message values. console.log('Retrieved message content: ', message); // Run moderation checks on on the message and moderate if needed. const moderatedMessage = moderateMessage(message.text); // Update the Firebase DB with checked message. console.log('Message has been moderated. Saving to DB: ', moderatedMessage); return event.data.adminRef.update({ text: moderatedMessage, sanitized: true, moderated: message.text !== moderatedMessage }); } });
In the moderateMessage function, we'll first check if the user is shouting and if so fix the case of the sentence and then remove all bad words using the bad-words package filter.
moderateMessage
bad-words
function moderateMessage(message) { // Re-capitalize if the user is Shouting. if (isShouting(message)) { console.log('User is shouting. Fixing sentence case...'); message = stopShouting(message); } // Moderate if the user uses SwearWords. if (containsSwearwords(message)) { console.log('User is swearing. moderating...'); message = moderateSwearwords(message); } return message; } // Returns true if the string contains swearwords. function containsSwearwords(message) { return message !== badWordsFilter.clean(message); } // Hide all swearwords. e.g: Crap => ****. function moderateSwearwords(message) { return badWordsFilter.clean(message); } // Detect if the current message is shouting. i.e. there are too many Uppercase // characters or exclamation points. function isShouting(message) { return message.replace(/[^A-Z]/g, '').length > message.length / 2 || message.replace(/[^!]/g, '').length >= 3; } // Correctly capitalize the string as a sentence (e.g. uppercase after dots) // and remove exclamation points. function stopShouting(message) { return capitalizeSentence(message.toLowerCase()).replace(/!+/g, '.'); }
Note: the bad-words package uses the badwords-list package's list of swear words which only contains around 400 of these. As you know the imagination of the user out there has no limit, so this is not an exhaustive list and you might want to extend the bad words dictionary.
To moderate images we'll set up a blurOffensiveImages function that will be triggered every time a file is uploaded to Cloud Storage. We set this up by using the functions.cloud.storage().onChange(...) trigger rule. We'll check if the image contains violent or adult content using the Google Cloud Vision API. The Cloud Vision API has a feature that specifically allows to detect inappropriate content in images. Then if the image is inappropriate we'll blur the image:
blurOffensiveImages
functions.cloud.storage().onChange(...)
exports.blurOffensiveImages = functions.storage.object().onChange(event => { const object = event.data; const file = gcs.bucket(object.bucket).file(object.name); // Exit if this is a move or deletion event. if (object.resourceState === 'not_exists') { return console.log('This is a deletion event.'); } // Check the image content using the Cloud Vision API. return vision.detectSafeSearch(file).then(data => { const safeSearch = data[0]; console.log('SafeSearch results on image', safeSearch); if (safeSearch.adult || safeSearch.violence) { return blurImage(object.name, object.bucket, object.metadata); } }); });
To blur the image stored in Cloud Storage, we'll first download it locally on the Cloud Functions instance, blur the image with ImageMagick, which is installed by default on all instances, then re-upload the image to Cloud Storage:
function blurImage(filePath, bucketName, metadata) { const filePathSplit = filePath.split('/'); filePathSplit.pop(); const fileDir = filePathSplit.join('/'); const tempLocalDir = `${LOCAL_TMP_FOLDER}${fileDir}`; const tempLocalFile = `${LOCAL_TMP_FOLDER}${filePath}`; const bucket = gcs.bucket(bucketName); // Create the temp directory where the storage file will be downloaded. return mkdirp(tempLocalDir).then(() => { console.log('Temporary directory has been created', tempLocalDir); // Download file from bucket. return bucket.file(filePath).download({ destination: tempLocalFile }); }).then(() => { console.log('The file has been downloaded to', tempLocalFile); // Blur the image using ImageMagick. return exec(`convert ${tempLocalFile} -channel RGBA -blur 0x8 ${tempLocalFile}`); }).then(() => { console.log('Blurred image created at', tempLocalFile); // Uploading the Blurred image. return bucket.upload(tempLocalFile, { destination: filePath, metadata: {metadata: metadata} // Keeping custom metadata. }); }).then(() => { console.log('Blurred image uploaded to Storage at', filePath); }); }
Cloud Functions for Firebase can be a great tool to reactively and automatically apply moderation rules. Feel free to have a look at our open source samples for text moderation and image moderation.
When Firebase was first released, it came with a number of authentication schemes:
You could build an app for email & password authentication (iOS, Android, Web), where the user provides you with basic details -- and Firebase would manage signing in using those as their identity. You could also build using federated identity where, instead of signing up for your app, users could simply sign in using credentials provided by third parties such as Google, Facebook, Twitter or GitHub, or anonymous authentication where you could apply security rules to people who haven't yet signed up.
One type of authentication that was requested by a number of developers was the ability to sign in using a phone number. With that in mind, we're delighted to announce that Firebase Auth now supports phone number authentication. If you're currently using the Digits SDK for phone number auth, check out the announcement here for details on the migration to Firebase Auth.
Here's how Firebase Phone Auth works.
Here's an example of an app that supports phone auth as well as federated identity via Google and Facebook, and basic email/password authentication.
It has been built using FirebaseUI, so many of the flows that you see in this article are automatically implemented for you when you integrate it.
As you can see at the bottom of the screen, there's a 'Sign in with Phone' option.
Let's take a look at what happens when the user taps that.
When the user first taps the Sign In with Phone button, they’ll enter the phone number for the device. When they press ‘Verify’, the number will be sent to Firebase, which will generate a 6-digit code that is sent via SMS to their device.
If the user enters the correct code, Firebase will validate them and add them as a recognized user. They’ll then stay signed in for future sessions.
You’ll see them as a verified user in the Firebase Console:
You can learn more about Firebase Authentication on the Firebase Developers Site.
Firebase UI is an Open Source library that lets you quickly get up and running with best-practice sign in and sign up flows. Phone Auth with Firebase UI is presently available on iOS and the Web, and coming soon to Android.
We're continuing to grow and build Firebase and Firebase Authentication, and we'd love to hear your feedback, so please reach out to us at firebase.google.com/support.
Here at Firebase, we know that the first step in making improvements in your app is knowing how your users are interacting with it: what parts they love, where they're having trouble, and what features are sadly underutilized. This is why we built Google Analytics for Firebase from the ground up to be a complete mobile analytics solution, with free and unlimited app analytics designed specifically for the way mobile apps are built.
Now, if you were paying close attention to the last paragraph, you may have noticed that the product formerly known as Firebase Analytics is now called "Google Analytics for Firebase." Don't worry; it's the same analytics product you know and love -- and we'll talk more about the name change in a bit.
Over the last year, we've made a number of improvements to Google Analytics for Firebase, including adding StreamView, which gives you an impression of how users are interacting with your app at this very moment, and DebugView, which allows you to see in precise detail what analytics events (and errors!) might be happening on a test device.
This year at Google I/O, we were thrilled to announce a number of new improvements and enhancements that make using analytics even better. In case you missed those presentations (which you can also watch on YouTube), let's give you a quick summary of what's new with Google Analytics for Firebase.
With Google Analytics for Firebase, you're allowed to submit up to 25 custom parameters alongside any events that you record in your app. For instance, if you were submitting a end_of_round event in a game, you could submit a user_score or premium_coins_earned parameter along with that event. By analyzing these different parameter values, you could then ensure that your game had the high score distribution or general payout rate that you were expecting.
end_of_round
user_score
premium_coins_earned
But up until now, it's been impossible to see the results of most of these custom event parameters without first exporting your data to BigQuery and doing the analysis there. Being able to view summaries of these event parameters directly in the Firebase console has been our most common feature request since analytics first launched last year. So we're very pleased to announce that we've taken our first big steps in making these reports available to you.
To get started with custom event parameters in Firebase, you'll need to let Google Analytics for Firebase know what parameters you're interested in. You can do this by going to the specific event in the Firebase console and clicking the "Add event parameters" button in the interface. From there, you can specify a parameter, note whether it's a number or a string, and add units of measurement, if applicable.
Once you've done that, you'll start seeing these parameter summaries directly in the console. We'll show you sums and averages for numeric values, and a list of your most popular values for strings.
Like other analytics reports available in Google Analytics for Firebase, you can filter these reports by user properties or audiences to get a better sense of how different users are interacting with your app in different ways.
Currently, you can specify up to 50 different event parameters for which you'd like to generate summary reports.
Of course, if you want to analyze a greater number of custom event parameters, or want to do more sophisticated analysis than what's available from the Firebase console, you can export your Google Analytics data directly into BigQuery, Google's data warehouse in the cloud. Analyzing your data in BigQuery is a very powerful way of running all sorts of ad hoc queries or custom analysis on your data, and we want to encourage all our developers to try it out.
To assist you on your journey, we've now added a free tier of storage in BigQuery -- 10 GB of data to be exact -- for every project using Google Analytics for Firebase. Combine this free storage tier with the 1 TB of free monthly query usage that you get from BigQuery, and you can do an awful lot of BigQuery analysis for a relatively little amount of money. And with the new analytics report templates in Data Studio, making stylish reports on custom parameters (or anything else you can measure in BigQuery) is a cinch.
We've made some major enhancements in the way Firebase and AdMob communicate with each other. Much like milk and cookies1, mixing Firebase and AdMob together results in an exciting new flavor combination that complements the strengths of both products!
By linking your AdMob account to Firebase, your app will automatically record analytics events associated with AdMob (along with mediated ad units) just like any other analytics event. This gives Google Analytics for Firebase the ability to create reports on ad impressions, clicks, and exposure time, broken down by important characteristics such as screen, ad format or ad unit. This makes it easier than ever before to see which ads are most effective in your app, where you're earning the most ad dollars, or which ads your users spend the most time viewing.
Linking your AdMob and Firebase accounts together also gives you a more complete picture of where you're making money in your app. Both the APRU reports on the dashboard and the Lifetime Value metrics in the Attribution reports will now include revenue generated from AdMob advertising, as well as in-app purchases.
This can help you gain a much more complete understanding of how your app is doing from a revenue standpoint, and help you more accurately gauge which growth campaigns are bringing you users who are earning you the most revenue.
If, like me, you enjoy spending your free time reading the latest Firebase Release Notes, you might have noticed that a few months ago, Firebase started adding screen tracking support to the events that it was recording. This month, we're taking the first steps towards adding screen tracking reports in Google Analytics for Firebase, by showing you the top three screens your users are spending time on. You can find this information in the User Engagement section of the Firebase Dashboard.
Screen tracking reporting works behind the scenes by automatically logging a screen_view event whenever a screen transition occurs. These events are then combined on the server to paint a more complete picture of the user's journey throughout your app. And just like any other event, you can view them in StreamView or DebugView, or analyze them through BigQuery. If you would like to customize these events -- for instance, you're a game developer who has multiple "screens" all within the same ViewController -- you can do so with by setting these events manually on the client.
screen_view
You can already use Google Analytics for Firebase for attribution tracking, which helps you learn not just which ad networks are sending you users, but which ones are sending you valuable users that you care about the most. And we're pleased to announce a new integration with DoubleClick Digital Marketing that will include attribution tracking for DoubleClick Campaign Manager and Bid Manager. Add this to the 50+ third-party advertising networks (and growing!) that we've integrated into our system, and Firebase can help you make better decisions around where to spend your advertising dollars with true cross-network attribution data.
If you're using the old Google Analytics Services SDK in your existing apps, don't worry; it's not going anywhere. But we encourage you to start adding the Firebase SDK in future releases. Using the Firebase SDK will give you access to the latest reports in Google Analytics for Firebase and to new functionality as it becomes available. If you're a long-time Google Analytics fan, you can use Google Tag Manager to automatically send your events data to those reports as well. If you need more help on this topic, we wrote a blog post a few months back that covers a few strategies on how to get both these analytics libraries working together in your app. Give it a read sometime!
We're thrilled to be bringing you these improvements to Google Analytics for Firebase -- they should be already available in the Give it a read sometime today (check out the demo project for an example!). If you haven't yet added analytics to your product, you can find all the documentation you need here to get started. Give it a try, and let us know what you think!
1. Or chili and mango, which Steve Ganem assures me is delicious, but sounds weird to me.↩