[go: up one dir, main page]

Francis Ma
Head of Product

This week, we’re returning to Google I/O for the 4th year in a row to share how we’re making Firebase better for all app developers, from the smallest one-person startup to the largest enterprise businesses. No matter how many times we take the stage, our mission remains the same: to help mobile and web developers succeed by making it easier to build, improve, and grow your apps. Since launching Firebase as Google’s mobile development platform at I/O 2016, we’ve been continuously amazed at what you’ve built with our tools. It is an honor to help you on your journey to change the world!

For example, in Uganda, a start-up called Teheca is using Firebase to reduce the mortality rate of infants and new mothers by connecting parents with nurses for post-natal care. Over in India where smartphones are quickly replacing TVs as the primary entertainment source, Hotstar, India’s largest video streaming app, is using Firebase with BigQuery to transform the viewing experience by making it more social and interactive. Here’s how they’re doing it, in their own words:

Stories like these inspire us to keep making Firebase better. In fact, we’ve released over 100 new features and improvements over the last 6 months! Read on to learn about our biggest announcements at Google I/O 2019.

Simplifying machine learning for every app developer

New translation, object detection and tracking, and AutoML capabilities in ML Kit

Last year, we launched ML Kit, bringing Google's machine learning expertise to mobile developers in a powerful, yet easy-to-use package. It came with a set of ready-to-use on-device and cloud-based APIs with support for custom models, so you could apply the power of machine learning to your app, regardless of your familiarity with ML. Over the past few months, we’ve expanded on these by adding solutions for Natural Language Processing, such as Language Identification and Smart Reply APIs. Now, we’re launching three more capabilities in beta: On-device Translation API, Object Detection & Tracking API, and AutoML Vision Edge.

The On-device Translation API allows you to use the same offline models that support Google Translate to provide fast, dynamic translation of text in your app into 58 languages. The Object Detection & Tracking API lets your app locate and track, in real-time, the most prominent object in a live camera feed. With AutoML Vision Edge, you can easily create custom image classification models tailored to your needs. For example, you may want your app to be able to identify different types of food, or distinguish between species of animals. Whatever your need, just upload your training data to the Firebase console and you can use Google’s AutoML technology to build a custom TensorFlow Lite model for you to run locally on your user's device. And if you find that collecting training datasets is hard, you can use our open source app which makes the process simpler and more collaborative.

Customers like IKEA, Fishbrain, and Lose It! are already using ML Kit’s capabilities to enhance their app experiences. Here’s what they had to say:

"We’re working with Google Cloud to create a new mobile experience that enables customers, wherever they are, to take photos of home furnishing and household items and quickly find that product or similar in our online catalogue. The Cloud Vision Product Search API provided IKEA a fast and easy way to index our catalogue, while ML Kit’s Object Detection and Tracking API let us seamlessly implement the feature on a live viewfinder on our app. Google Cloud helps us make use of Vision Product Search and we are very excited to explore how this can help us create a better and more convenient experience for our customers.”
- Susan Standiford, Chief Technology Officer of Ingka Group, a strategic partner in the IKEA franchise system and operating IKEA in 30 markets.
“Our users are passionate about fishing, so capturing and having access to images of catches and species information is central to their experience. Through AutoML Vision Edge, we’ve increased the number of catches logged with species information by 30%, and increased our species recognition model accuracy from 78% to 88%..”

- Dimitris Lachanas, Android Engineering Manager at Fishbrain
“Through AutoML Vision Edge, we were able to create a highly predictive, on-device model from scratch. With this improvement to our state-of-the-art food recognition algorithm, Snap It, we’ve increased the number of food categories our customers can classify in images by 21% while reducing our error rate by 36%, which is huge for our customers.” - Will Lowe Ph.D., Director of Data Science & AI, Lose It!

Providing deeper insight into speed & performance of web apps

Performance Monitoring now supports web apps

Native mobile developers have loved using Firebase Performance Monitoring to find out what parts of their app are running slower than they expect, and for which app users. Today, we’re excited to announce that Performance Monitoring is available for web apps too, in beta, so web developers can understand how real users are experiencing their app in the wild.

By pasting a few lines of code to their site, the Performance Monitoring dashboard will track and visualize high level web metrics (like page load and network stats) as well as more granular metrics (like time to first paint and first input delay) across user segments. The Performance Monitoring dashboard will also give you the ability to drill down into these different user segments by country, browser, and more. Now, you can get deep insight into the speed and performance of your web apps and fix issues fast to ensure your end users have a consistently great experience. By adding web support to one of our most popular tools, we’re reaffirming our commitment to make app development easier for both mobile and web developers.

Firebase Performance Monitoring dashboard

Enhancing user segmentation capabilities for better personalization & analysis

Brand new audience builder in Google Analytics for Firebase

Google Analytics for Firebase provides free, unlimited, and robust analytics so you can measure the things that matter in your app and understand your users. A few weeks ago, we announced advanced filtering in Google Analytics for Firebase, which allows you to filter your Analytics event reports by any number of different user properties or audiences at the same time.

Today, we’re thrilled to share that we’ve completely rebuilt our audience system from scratch with a new interface. This new audience builder includes new features like sequences, scoping, time windows, membership duration, and more to enable you to create dynamic, precise, and fresh audiences for personalization (through Remote Config) or re-engagement (through Cloud Messaging and/or the new App campaigns).

For example, if you wanted to create a "Coupon users" audience based on people who redeem a coupon code within your app, and then complete an in-app purchase within 20 minutes, this is now possible with the new audience builder.

Audience builder on the Firebase Performance Monitoring dashboard

Other exciting announcements from I/O

In addition to the three big announcements above, we’ve also made the following improvements to other parts of Firebase.

Support for collection group queries in Cloud Firestore

In January, we graduated Cloud Firestore - our fully-managed NoSQL database - out of beta into general availability with lower pricing tiers and new locations. Now, we’ve added support for Collection Group queries. This allows you to search for fields across all collections of the same name, no matter where they are in the database. For example, imagine you had a music app which stored its data like so:

Cloud Firestore data storage structure flowchart example with artists in tier one and songs in tier two

This data structure makes it easy to query the songs by a given artist. But until today, it was impossible to query across artists — such as finding the longest songs regardless of who wrote them. With collection group queries, Cloud Firestore now can perform these searches across all song documents, even though they're in different collections. This means it’s easier to organize your data hierarchically, while still being able to search for the documents you want.

Cloud Functions emulator

We’ve also been steadily improving our tools and emulator suite to increase your productivity for local app development and testing. In particular, we’re releasing a brand new Cloud Functions emulator that can also communicate with the Cloud Firestore emulator. So if you want to build a function that triggers upon a Firestore document update and writes data back to the database you can code and test that entire flow locally on your laptop, for much faster development.

Configurable velocity alerts in Crashlytics

Firebase Crashlytics helps you track, prioritize, and solve stability issues that erode app quality, in real time. 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. We’re also happy to announce that we’ve expanded Crashlytics to include Unity and NDK support.

Velocity alert settings

Improvements to Test Lab

Firebase Test Lab makes it easy for you to test your app on real, physical devices, straight from your CLI or the Firebase console. Over the past few months, we’ve released a number of improvements to Test Lab. We’ve expanded the types of apps you can run tests on by adding support for Wear OS by Google and Android App Bundles. We’ve also added ML vision to Test Lab’s monkey action feature so we can more intelligently simulate where users will tap in your app or game. Lastly, we’ve made your tests more reliable with test partitioning, flaky test detection, and the robo action timeline, which tells you exactly what the crawler was doing while the test was running.

Greater control over Firebase project permissions

Security and data privacy remain part of our top priorities. We want to make sure you have control over who can access your Firebase projects, which is why we’ve leveraged Google Cloud Platform’s Identity & Access Management controls to give you finer grained permission controls. Right from the Firebase console, you can control who has access to which parts of your Firebase project. For example, you can grant access to a subset of tools so team members who run notification campaigns aren’t able to change your Firebase database’s security rules. You can go even further and use the GCP console to create custom roles permitting access to only the actions your team members are required to take.

More open-sourced SDKs

To make Firebase more usable and extensible, we’re continuing to open source our SDKs and accepting contributions from the community. We are committed to giving you transparency and flexibility with the code you integrate into your mobile and web apps. Most recently, we open sourced our C++ SDK.

Recapping a few updates from Cloud Next 2019

In case you missed the news at Cloud Next 2019, here’s a quick recap of the updates we unveiled back in April:

  • Firebase Hosting and Cloud Run integration: This integration combines Firebase Hosting's global CDN and caching features with Cloud Run's fully managed stateless containers. Now, it’s easier than ever to add performant server-side rendering for your websites in any language you want, without having to provision or manage your own servers.
  • Paid enterprise-grade support: The Google Cloud Platform (GCP) support plan includes support for Firebase products, which is a new option for our larger customers who are interested in a more robust, paid support experience. As a reminder, free community support isn’t going anywhere!

Update on Fabric migration

In addition to making Firebase more powerful, we’ve also been hard at work bringing the best of Fabric into Firebase. We know many of you have been waiting for more information on this front, so we have outlined our journey in more detail here.

Onwards

We’re continuing to invest in Firebase and as always, we welcome your feedback! With every improvement to Firebase, we aim to simplify your app development workflows and infrastructure needs, so you can stay focused on building amazing user experiences. To get a sneak peek at what’s next, join our Alpha program and help us shape the future

Patrick Martin
Developer Advocate

Today we're excited to announce Firebase Hosting integration for Google Cloud’s new Cloud Run service. Cloud Run is a fully managed compute platform that enables developers to run stateless containers that are invocable via HTTP requests in a language and framework of their choosing. Firebase Hosting integration lets you use this architecture as a backend for a web app or microservice in your Firebase project.

Firebase Hosting is already a convenient and secure way to host sites and microservices. It can serve static pages you upload directly and, with the proper configuration in the firebase.json file, direct incoming requests to Cloud Functions for Firebase to serve dynamic content. This workflow is a one stop shop if you don’t mind working in the NodeJS environment. You can already build a fast site with dynamic content that automatically scales horizontally to meet user demand.

Not every developer wants to work with NodeJS though. Many already have large teams with existing knowledge in other languages and frameworks. Languages such as Go, Ruby, and Java have a huge presence in the server market but are currently absent in Firebase’s existing cloud backend solutions.

Leveraging the power of Google’s own experience building infrastructure for Kubernetes and the efforts of the Knative open source project, Google Cloud Platform now lets you deploy stateless servers. The only requirements are that you can generate a docker image able to interact to HTTP requests on the port specified in the $PORT environment variable for Kubernetes and that you respond within 60 seconds for Firebase Hosting. How does this tie into Firebase Hosting though?

If you’re new to Hosting, you may only be aware of static hosting or the free SSL certificates. To facilitate serving dynamic content, rewrites allow you to hit your cloud functions, which we’ve extended to support Cloud Run as well. With a few minor changes to your firebase.json file, you can now point a specific path to your container:

{
  "hosting": {
    "public": "public",
    "rewrites": [ {
      "source": "/cloudrun",
      "run": {
        "serviceId": "my-awesome-api",
        // Optional (default is us-central1)
        "region": "us-central1",
      }
    } ]
  }
}

or use wildcards to expose an entire API

{
  "hosting": {
    "public": "public",
    "rewrites": [ {
      "source": "/api/**",
      "run": {
        "serviceId": "my-awesome-api",
        // Optional (default is us-central1)
        "region": "us-central1",
      }
    } ]
  }
}

If you have a dynamic site that doesn’t update very frequently, take advantage of Firebase Hosting’s global CDN (content delivery network) to improve your site’s response time. For example, if you’re using ExpressJS and NodeJS, configure the caching behavior using the Cache-Control header like so:

 res.set('Cache-Control', 'public, max-age=300, s-maxage=600');

which caches the results of a request in the browser (max-age) for 5 minutes and in the CDN (s-maxage) for 10 minutes. With properly tuned cache settings, you can have a fast, flexible, dynamically rendered site that doesn’t need to run your server logic every time the user opens the page.

Unlike Cloud Functions for Firebase, when you use Cloud Run, you can build an image with any combination of languages and frameworks to handle these requests. Ruby developers can easily pull in Sinatra, you can fire up the Spring framework for Java teams, or check out server side Dart using Shelf to serve content. You don’t have to wait for any official language support -- if you can create a docker container, you can make and deploy backend code. Even if you’re working in high performance computing and your engineering team is trained up in Fortran, you can just leverage that existing knowledge to create a web dashboard with Fortran.io without having to wait for any official support from Google or Firebase.

Similar to Cloud Functions, Cloud Run automatically scales your containers horizontally to meet the demands of your users. There’s no need to manage clusters or node pools; you simply use the resources needed at the time to accomplish the task at hand. One tradeoff is that, also like Cloud Functions, Cloud Run images are stateless. However, unlike Cloud Functions, each container can handle up to 80 concurrent users, which can help reduce the frequency of cold starts.

Using Firebase Hosting with Cloud Run, we hope to empower you to build better web apps faster than ever before. Now your frontend and backend developers can truly use a single language, even share a code base. To get started right away, follow our step-by-step guide. Note that Cloud Run exists in the Google Cloud console rather than the Firebase console, but if you have a Firebase project then you already have a Google Cloud Platform project as well.


Diana Tkachenko
Diana Tkachenko
Software Engineer

Alex Memering
Alex Memering
Software Engineer

Do you manage multiple Firebase Hosting sites? Do these sites share a single resource like a Firestore or Realtime database? Do you wish you could manage these sites from one place instead of having to create multiple projects? Do you wish that Firebase Hosting could deploy only the new or modified files? Wish no more! Because it's all here!

Create multiple sites in one project

Firebase Hosting now allows you to create multiple sites inside of one Firebase project. If your admin site and blog site consume data from a shared Firebase resource, they can now both live in a single project - saving you time and developer resources. You can manage these sites directly in the Firebase Console and deploy via the command line.

Firebase automatically provisions a firebaseapp domain for you, which is the same as your Firebase project name. We currently do not support subdomains on the firebaseapp.com domain, but you can still provision subdomains on your own by connecting a custom domain for your sites. To get started with multiple sites, you'll need to be on the Blaze plan. Once you're on the Blaze plan you'll be able to add multiple sites inside of the Firebase Console.

Configure targets for multiple sites in firebase.json

To help switch between different sites in a single project we introduced a new configuration setup in firebase.json. Make sure you update to the latest version of the Firebase CLI!

{
  "hosting": [ {
      "target": "blog",
      "public": "blog/dist"
    }, {
      "target": "app",
      "public": "app/dist"
    }
  ]
}

The "hosting" config can now take in an array of site configurations. A single object still works if you still have just one site. Each configuration has a "target". The CLI uses this target to know what "public" folder to use for deploying assets. Speaking of the CLI! We have a new command for you.

Deploy from the CLI with targets

To manage switching between multiple sites in one project, we're going to use the target:apply command. This command is a bit like the firebase use --add command except instead of linking the project to the alias, it establishes a link between the site and the target. The applied target can then be used with the firebase deploy and firebase serve commands.

The firebase use command is helpful for deploying to multiple projects. This is common for those who have a "staging" project versus a "production" project. For managing one site across different environments, we still recommend multiple projects for promoting best practices of each environment having its own set of Firebase resources.

However, managing multiple sites is a different problem. The CLI now has to know about multiple sites instead of just one. The CLI must know:

  • The name of the specific site
  • Where the assets of this site are located
  • What project you wish to deploy this site to

This why we introduced target:apply for Hosting.

firebase target:apply hosting target-name site-name

Let's break down this command.

  • firebase - the Firebase CLI module
  • target:apply - the command to link the site to the target
  • hosting - the Firebase resource type of the target
  • target-name - the target name specified in firebase.json. You could use "blog" or "app" as in the example config above.
  • site-name - the name of the site you want the target associated with

Let's say you wanted to deploy your blog using the example firebase.json above:

firebase target:apply hosting blog my-cool-blog
firebase deploy --only hosting:blog

In this command, we first identified the target-name of "blog", then associated it with the targeted site "my-cool-blog", and finally deployed to that target. If you don't specify a target in your firebase deploy or firebase serve commands, then all your targets will be deployed, or served locally on different ports, respectively. Note that you only have to define your targets once per project.

Your uploads just got a bit faster, and in some cases a lot faster

If you updated the Firebase CLI recently, you might have noticed that your uploads got a bit faster. You may have also noticed a new .firebase folder in your project. That's because we rolled up a new deployment system that we call Delta Uploads.

This new system only processes new, modified, or deleted files. You know, the delta. This means any files that are unchanged aren't uploaded when you run firebase deploy. You may not notice a big improvement in performance if your site is only a few files. However, it will make a huge difference for sites with a large amount of existing unmodified assets.

Give it a try today!

Check out the official documentation and make sure to update your CLI! Both multi-site and delta uploads features require the latest version of the Firebase CLI. Make sure you're either above or at version 4.2.0 to use these features. Happy deploying!

Doug Stevenson
Doug Stevenson
Developer Advocate
If you've browsed the web at all, you've probably seen some sites that ask you to prove you're a human by presenting a reCAPTCHA challenge. For example, if you try to use the goo.gl URL shortener, it won't let you shorten a link until you satisfy the reCAPTCHA, which looks like this:

Web site engineers do this to protect their site from spam and abuse from bots, while allowing legitimate human use. Why is protection needed? Maybe you have some backend code that's expensive in time and storage and you only want actual users of your web to access it.

If you have a web site, you can also use reCAPTCHA to protect its services. And, if you're building your site with Firebase Hosting, it's pretty easy to get it integrated with the help of Cloud Functions for Firebase to provide a secure, scalable backend to verify the completion of the reCAPTCHA.

In this blog post, I'll walk you through a few steps that will get you to a very basic integration that you can extend later for your own site. For this walkthrough, I'm assuming you already have some experience with web development, the Firebase console, and the Firebase CLI.

1. Create a Firebase project in the console

Navigate to the Firebase console and create a new project. There's no need to add billing to this project - you can experiment fully without providing a credit card. Once you create the project, there's nothing else you need to do in the console.

2. Set up a directory for your project code

Using the Firebase CLI, make sure you're logged in with the same Google account that you used to create the project:

$ firebase login

Now, create a root project directory and initialize it:

$ mkdir my_project
$ cd my_project
$ firebase init

When running firebase init, be sure to select both hosting and functions. When you're asked to choose a project, select the one you just created earlier. Take the defaults for every other prompt. You'll end up with a directory structure that contains a public folder for web content, and a functions folder for your backend code.

For the Cloud Functions backend, we'll need a couple modules from npm to help verify the reCAPTCHA. The reCAPTCHA API requires you to make an HTTP request for verification from your backend, and you can do that with the request and request-promise modules. Pull them into your project like this:

$ cd functions
$ npm install request request-promise

Your package.json file should now show those two new modules in addition to firebase-functions and firebase-admin.

3. Test web deployment

Make sure you can deploy web content by running this deploy command:

$ firebase deploy --only hosting

When this finishes, you'll be given the public URL to your new web site, which will look something like this:

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/your-project/overview
Hosting URL: https://your-project.firebaseapp.com

where your-project is the unique id that was given to your project at the time it was created in the console. If you paste the Hosting URL into your browser, you should see a page that says "Firebase Hosting Setup Complete".

4. Get a reCAPTCHA API Key

reCAPTCHA requires a couple API keys for operation, one for the web client and one for the server API. You can get those from the reCAPTCHA admin panel, so navigate there. Create a new site and give it a name. Select "reCAPTCHA V2". For domains, put the full hostname of your Firebase Hosting site name (e.g. "your-project.firebaseapp.com").

After you register, you'll be given a Site key and a Secret key. The Site key will be used in your frontend HTML, and the Secret key will be used in your backend hosted by Cloud Functions.

5. Add a page with a reCAPTCHA

Now we'll add a new HTML page to display the reCAPTCHA. In the public directory in your project, add a new HTML file called recaptcha.html to display the reCAPTCHA. Simply copy and paste the following content directly into that new file:

<html>
  <head>
    <title>Firebase + reCAPTCHA</title>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <script type="text/javascript">
    function dataCallback(response) {
        console.log("dataCallback", response)
        window.location.href = "/checkRecaptcha?response=" + encodeURIComponent(response)
    }
    function dataExpiredCallback() {
        console.log("dataExpiredCallback")
    }
    </script>
  </head>
  <body>
    <div class="g-recaptcha"
      data-sitekey="PASTE_YOUR_SITE_KEY_HERE"
      data-callback="dataCallback"
      data-expired-callback="dataExpiredCallback"/>
  </body>
</html>

Notice in the body there is a div with the class "g-recaptcha". The first thing you should do here is copy your reCAPTCHA site key into the div's data-sitekey attribute value. This div will get automatically transformed into a reCAPTCHA UI after the first script at the top is loaded. You can read more about that here in the docs.

You can see it right away if you firebase deploy again, then navigate to /recaptcha.html under your Hosting URL. Don't bother dealing with the reCAPTCHA yet, because we still need some backend code to complete the verification!

The JavaScript code in this page defines two functions dataCallback and dataExpiredCallback. These are referenced in the div, and provide callbacks for the reCAPTCHA to tell you when the reCAPTCHA has been satisfied, or if the user took too long to proceed.

The important thing to note in dataCallback is that it redirects the browser to another URL in the site with the path /checkRecaptcha, and pass it a parameter named response. This response string is generated by reCAPTCHA and looks like a random collection of characters.

The path /checkRecaptcha in your web site obviously doesn't exist yet, so we need to create a Cloud Function to validate the response string it's going to receive.

6. Create a Cloud Function to verify the reCAPTCHA response

In the functions directory in your project, edit the existing index.js file. This has some sample code, but you can delete it. In its place, paste the following JavaScript code:

const functions = require('firebase-functions')
const rp = require('request-promise')

exports.checkRecaptcha = functions.https.onRequest((req, res) => {
    const response = req.query.response
    console.log("recaptcha response", response)
    rp({
        uri: 'https://recaptcha.google.com/recaptcha/api/siteverify',
        method: 'POST',
        formData: {
            secret: 'PASTE_YOUR_SECRET_CODE_HERE',
            response: response
        },
        json: true
    }).then(result => {
        console.log("recaptcha result", result)
        if (result.success) {
            res.send("You're good to go, human.")
        }
        else {
            res.send("Recaptcha verification failed. Are you a robot?")
        }
    }).catch(reason => {
        console.log("Recaptcha request failure", reason)
        res.send("Recaptcha request failed.")
    })
})

The first thing you should do here is paste your reCAPTCHA secret key from the registration site in place of "PASTE_YOUR_SECRET_CODE_HERE".

(Astute readers may note that the reCAPTCHA API endpoint host is "recaptcha.google.com", while the docs say "www.google.com". This is OK! You have to use recaptcha.google.com as shown in order to make the call on the Spark plan, because that host has been whitelisted for outgoing traffic from Cloud Functions.)

This code defines an HTTPS function that, when triggered, will make another HTTPS request (using the request-promise module) to the reCAPTCHA API in order to verify the response that was received in the query string. Notice that there are three cases with three different responses to the client. Either:

  1. The reCAPTCHA verifies successfully (the user is human)
  2. The reCAPTCHA fails (could be a robot)
  3. The API call fails altogether

It's important to send a response to the client in all cases, otherwise the function will time out with an error message in the Firebase console log.

To deploy this new function (and the web content at the same time) run the following command:

$ firebase deploy

You'll notice in the output that the function is assigned its own URL, which looks something like this:

https://us-central1-your-project.cloudfunctions.net/checkRecaptcha

This is clearly a different host than the one with your web content. However, what we really want instead is for the function to be referenced through your web host at a URL that looks like this:

https://your-project.firebaseapp.com/checkRecaptcha

This makes the function look like it's part of your web site. With Firebase Hosting a Cloud Functions, this can be done!

7. Add rewrites to map a hosting URL to a Cloud Function

Edit the file firebase.json in the project root directory and paste the follow JSON configuration as its contents:

{
  "hosting": {
    "public": "public",
    "rewrites": [
      {
        "source": "/checkRecaptcha",
        "function": "checkRecaptcha"
      }
    ]
  }
}

What you've done here is add a new section for rewrites, and you can read more about those in the docs. Specifically what this does is allow access to the URL path /checkRecaptcha invoke the function called checkRecaptcha that you pasted into your functions/index.js file.

Remember that the JavaScript code in recaptcha.html redirects to this path when the reCAPTCHA is satisfied by the user, so this effectively sends to user to the function after they complete the reCAPTCHA.

Now do one final deploy to send everything to Firebase:

$ firebase deploy

8. Test the reCAPTCHA!

Navigate to /recaptcha.html under your hosting URL, then solve the reCAPTCHA. It may ask you to identify some cars or roads in a set of pictures. Once you've satisfied the reCAPTCHA with your humanity, the JavaScript in your HTML should redirect you to your function, which verifies with the server that you're indeed human, and you should see the message "You're good to go, human."

This example of how to use reCAPTCHA with Cloud Functions for Firebase is much more simple than what you'd probably do in your own web site. You have several options for how to send the reCAPTCHA response to your function, and you'd obviously want to provide something more useful than a message to the user. But this should get you started protecting your web content from abuse from bots.