Search⌘ K
AI Features

Background Trigger Functions

Explore how to create Cloud Functions that respond to background events in Firebase like user creation, database changes, and Firestore updates. Learn how to handle authentication triggers, monitor Realtime Database and Firestore events, and write functions that automate processes based on data changes. This lesson provides practical guidance on setting up triggers and managing event data for efficient app integrations.

In the Introduction to Cloud Functions lesson, we mentioned that we can trigger Cloud Functions in response to events coming from Firebase products. These types of functions are called background trigger functions. Examples of such event triggers include the following:

  • When a user signs up with Firebase authentication
  • A write, update, or delete operation on the Realtime Database or Cloud Firestore
  • A conversion event in Google Analytics

With the Cloud Functions for Firebase SDK, we can monitor these events and trigger a function in response to such events. This allows us to handle them the way we want to. Let’s take a look at some of these.

Note: All background trigger functions must be terminated by returning a promise that is fulfilled after the function completes all the work to be done. However, if there is no work, we can return null to terminate the function.

Authentication triggers

We can trigger Cloud Functions for Firebase in response to a user creation or a deletion event on our Firebase application. We do this by using either the onCreate or onDelete handlers with the functions.auth.user() function. These handlers take a callback function with a parameter, user. We use this parameter to access the user’s attributes, similar to the client SDK:

Javascript (babel-node)
const functions = require("firebase-functions");
// onCreate function
exports.userSignup = functions.auth.user().onCreate((user) => {
const name = user.displayName
const email = user.email
console.log("user created", user.displayName, user.uid);
// send welcome email
});
// onDelete function
exports.userDelete = functions.auth.user().onDelete((user) => {
// send goodbye email
});
  • Line 1: We call thefirebase-functions module and assign it to a constant, functions.
  • Line 4: We export the userSignup function. The functions.auth.user().onCreate method indicates that this function will only respond to user creation events.
  • Lines 5 and 6: We access the user object to retrieve the user’s name and email, respectively.
  • Line 8: We log the function status along with the user’s email and uid to the Firebase console. -Line 13: We export the userDelete function that responds to deletion events.

Realtime Database triggers

We can trigger Cloud Functions for Firebase in response to events in the Realtime Database. Cloud Functions wait for a change in a particular location on the database, as specified by the reference. They trigger when the specified event type occurs. Then, it receives a data object that contains a snapshot of the data after and, in some cases, before the trigger event.

We can create these functions using functions.database. Then, we must specify a path to the database location using the ref function. Then, we attach an event handler that triggers in response to specific event types. The Realtime Database supports four different event handlers:

  • onCreate: This triggers when new data is created on the Realtime Database.

  • onDelete: This triggers when data is deleted from the Realtime Database.

  • onUpdate: This triggers when a change is made to existing data in the Realtime Database.

  • onWrite: This responds to create, update, and delete operations to the location in the Realtime Database.

Javascript (babel-node)
const functions = require("firebase-functions");
// onCreate handler
exports.databaseTriggerSample = functions.database
.ref("/users/educative/tasks")
.onCreate((snapshot, context) => {
// do something
const uid = context.auth.uid;
// return something
return snapshot.val();
});
  • Line 1: We call the firebase-functions module required to run all Cloud Functions.
  • Line 4: We export our sample function, which is a database-triggered function.
  • Line 5: We define a path on the database that triggers the function. Here, we set our path to/users/educative/tasks.
  • Line 6: We call the onCreate method and pass in the snapshot and context parameters. The snapshot parameter contains a snapshot of the data stored in the location. The context parameter contains additional information about the user and the triggered event.
  • Line 8: We access the uid from the context object and assign it to a uid constant.
  • Line 11: We terminate the function with the return statement.

We can also use wildcards when defining the path reference. These allow us to match any child of the parent path in the location. We can access the values of the wildcard components under the context object as below:

C++
const functions = require("firebase-functions");
// onUpdate handler
exports.databaseTriggerSample = functions.database
.ref("/users/{userId}/tasks")
.onUpdate((change, context) => {
const wildcard = context.params.userId;
// do something
if (change.before.exists()) {
const old = change.before.val()
// do something
}
if (change.after.exists()) {
const new = change.after.val()
// do something
}
// return something
});

Let’s go over the snippet above:

  • Line 5: We define a path on the database that triggers the function. Notice the use of the wildcard,{}, in the path provided.

  • Line 6: We use the onUpdate handler and pass the change and context object parameters. The change object has a before and after property we can use to read data before and after the triggered event occurs.

  • Line 8: We access the value of the wildcard path from the context object and assign it to a wildcard constant. -** Lines 10, 11, 15, and 16:** We demonstrate how to check for the existence of the old and new data snapshots and access them if needed.

Note: Only the onUpdate and onWrite event handlers have access to the change object that contains a snapshot of the path before and after the trigger event. For onCreate and onDelete event types, the snapshot object returned is a snapshot of the data created or deleted. Read more about Realtime Database event triggers on the Firebase documentation.

Cloud Firestore triggers

Similarly, we can also trigger Cloud Functions for Firebase in response to events in Cloud Firestore. Cloud Firestore triggers work similar to Realtime Database triggers. However, they are accessed with functions.firestore and paths are referenced using the document function. Therefore, they wait for changes on a particular document path and trigger in response to those event types.

Cloud Firestore also has four triggers-onCreate, onDelete, onUpdate, and onWrite—which work the same as Realtime Database triggers discussed above:

Javascript (babel-node)
const functions = require("firebase-functions");
// onUpdate handler
exports.firestoreTriggerSample = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const newValue = change.after.data();
const previousValue = change.before.data();
const wildcard = context.params.userId;
// perform desired operations ...
// return something
return change.after.ref.set({
// update field
}, {merge: true})
});
  • Line 4: We export our Cloud Firestore triggered function.
  • Line 5: We define the document path for the function.
  • Line 6: We specify an event type for the function trigger. In our case, we use onUpdate. This accepts two parameters, change and context.
  • Lines 7 and 8: We access the new and previous data snapshot at the location using the change object. -Line 16: We terminate the function by returning a promise of a set operation.

Note: Our trigger must always point to a document, even if we’re using a wildcard. For example, users/{userId}/{tasks} is not valid because {tasks} is a collection. Read more about Cloud Firestore event triggers on the Firebase documentation.

You may have been wondering why we have not required the Admin SDK to perform some write operations such as we do on line 16 above?

Note: This only occurs when we write to the same location that triggers the event. Hence, making changes to other locations outside the trigger event or to other Firebase services will require the Admin SDK. This is shown below:

Javascript (babel-node)
const admin = require('firebase-admin');
admin.initializeApp();
exports.writeToFirestore = functions.firestore
.document('some/doc')
.onWrite((change, context) => {
admin.firestore().doc('some/otherdoc').set({ ... });
});

On line 8 above, we use the Admin SDK to write to a document outside our trigger event.

Practice exercise

Study the highlighted lines in the widget below to understand authentication triggers:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

admin.initializeApp();

// auth background trigger
exports.userSignup = functions.auth.user().onCreate((user) => {
  console.log("USER CREATED", user.displayName, user.uid);
  return null;
});

// http request function
exports.getTasks = functions.https.onRequest((request, response) => {
  admin
    .database()
    .ref("/tasks")
    .get()
    .then((snapshot) => {
      response.send(snapshot.val());
    })
    .catch((error) => {
      console.log(error.message);
      response.status(500).send(error.message);
    });
});
Background trigger functions

Steps to perform

  • Run the widget above.
  • Run the Cloud Functions deploy command on the terminal window provided. Don’t forget to include the required flags—--flags—and their respective values— $VALUES.
  • Open the application using the unique Educative link provided on the widget.
  • If logged in, log out of the existing account. Then, create a new user account using any sign-up method of your choice.
  • Head over to the “Logs” section of the “Functions” section of the Firebase console to view the logged output.

Note: The widget above only demonstrates an Authentication-triggered event. A more practical use case is to send welcome emails to new users of an application using tools like Nodemailer and SendGrid.