When you create an extension, you write its logic using Cloud Functions, in
much the same way as you would write a function that would only ever be used in
your own project. You declare your functions in the extension.yaml
file, and
when users install your extension, these functions get deployed into their
project.
See the Cloud Functions documentation for general information on using Cloud Functions.
1st and 2nd generation Cloud Functions
Firebase supports both 1st-generation and 2nd-generation Cloud Functions. However, Firebase Extensions currently have some restrictions on which generation of cloud function you can use with certain trigger types. For this reason, many extensions include a mix of 1st and 2nd generation functions.
Function generation support is noted for each trigger type, below.
Special considerations
Some function definitions require you to specify information that is also specified in the
extension.yaml
file. For example, Cloud Firestore has adocument()
method that specifies the document pattern to watch, and its corresponding declaration inextension.yaml
has aresource
field that specifies the same.In these situations, the configuration specified in the
extension.yaml
file is used and the configuration specified in the function definition is ignored.It is common practice to specify the configured value in the function definition regardless, for the sake of documentation. The examples on this page follow this pattern.
The Cloud Functions 1st gen SDK has a
functions.config()
method andfunctions:config:set
CLI command that you can use to work with parameterized values in 1st gen functions. This technique is deprecated in Cloud Functions and will not work at all in an extension. Instead, use thefunctions.params
module (recommended) orprocess.env
.
Using TypeScript
Most of the documentation for developing your own extension describes workflows using JavaScript for Cloud Functions for Firebase. However, you can instead write your functions using TypeScript.
In fact, all the official Firebase extensions are written in TypeScript. You can review those extensions for some best practices to use TypeScript for your extension.
If you do write your extension's functions in TypeScript, you must do the following before installing your extension:
Compile your extension's functions source code to JavaScript.
The
firebase ext:dev:init
command allows you to choose TypeScript for writing your functions. The command provides you with a complete, installable extension as well as a build script that you can run withnpm run build
.In your
package.json
file, make sure to point themain
field at the generated JavaScript.If you're installing or uploading your extension from local source, compile your TypeScript files first.
Supported function triggers
HTTP triggers
An HTTP-triggered function is deployed to a public https
endpoint and runs
when the endpoint is accessed.
See Call functions via HTTP requests in the Cloud Functions documentation for information on writing HTTP-triggered functions.
Function definition (1st-gen only)
import { https } from "firebase-functions/v1";
export const yourFunctionName = https.onRequest(async (req, resp) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
runtime: nodejs16
httpsTrigger: {}
- name: anotherFunction
type: ...
Callable functions
Callable functions are similar to HTTP-triggered functions, but they implement a protocol that makes them convenient to call from your client-side code.
See Call functions from your app in the Cloud Functions documentation for information on using callable functions.
Function definition (1st-gen only)
import { https } from "firebase-functions/v1";
export const yourFunctionName = https.onCall(async (data, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
runtime: nodejs16
httpsTrigger: {}
- name: anotherFunction
type: ...
Scheduled function triggers
A scheduled function runs repeatedly based on a customizable schedule.
See Schedule functions in the Cloud Functions documentation for information on writing scheduled functions.
Function definition (1st-gen only)
import { pubsub } from "firebase-functions/v1";
export const yourFunctionName = pubsub.schedule("every 6 hours").onRun((context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
scheduleTrigger:
schedule: 'every 5 minutes'
- name: anotherFunction
type: ...
Here are the available subfields for scheduleTrigger
:
Field | Description |
---|---|
schedule (required) |
The frequency at which you want the function to run. This field can accept strings that use either syntax (wrapping in single-quotes is required):
|
timeZone (optional) |
The time zone in which the schedule will run.
|
If you want users to be able to configure the schedule when they install your
extension, add a new parameter to your extension.yaml
file and reference the
parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
scheduleTrigger:
schedule: ${SCHEDULE_FREQUENCY}
- name: anotherFunction
type: ...
params:
- param: SCHEDULE_FREQUENCY
label: Schedule
description: How often do you want to run yourFunctionName()?
type: string
default: 'every 5 minutes' # Specifying a default is optional.
required: true
Task queue triggers
A task queue function is triggered either on your extension's lifecycle
events or when manually added to your extension's task queue using the Admin
SDK's TaskQueue.enqueue()
method.
See Handle your extension's lifecycle events for information on writing functions that handle lifecycle events.
See Enqueue functions with Cloud Tasks in the Cloud Functions documentation for information on writing task queue functions.
Function definition (1st-gen only)
import { tasks } from "firebase-functions/v1";
export const yourFunctionName = tasks.taskQueue().onDispatch(async (data, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: myTaskFunction
type: firebaseextensions.v1beta.function
description: >-
Perform a task when triggered by a lifecycle event
properties:
taskQueueTrigger: {}
Set the taskQueueTrigger
property set to either {}
or a map of options which
tune the rate limits and retry behavior of the task queue (see Tuning the task
queue).
If you want to trigger your function on your extension's lifecycle events, add
lifecycleEvents
records with the name of the function and an optional
processing message, which will be displayed in the Firebase console when
processing begins.
lifecycleEvents:
onInstall:
function: myTaskFunction
processingMessage: Resizing your existing images
onUpdate:
function: myOtherTaskFunction
processingMessage: Setting up your extension
onConfigure:
function: myOtherTaskFunction
processingMessage: Setting up your extension
Analytics
An Analytics-triggered function runs when a specified Analytics event gets logged.
See Google Analytics triggers in the Cloud Functions documentation for information on writing Analytics-triggered functions.
Function definition (1st-gen only)
import { analytics } from "firebase-functions/v1";
export const yourFunctionName = analytics.event("event_name").onLog((event, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/google.firebase.analytics/eventTypes/event.log
resource: projects/${PROJECT_ID}/events/ga_event
- name: anotherFunction
type: ...
If you want users to be able to configure the Analytics event to listen for
when they install your extension, add a new parameter to your extension.yaml
file and reference the parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/google.firebase.analytics/eventTypes/event.log
resource: projects/${PROJECT_ID}/events/${EVENT_NAME}
- name: anotherFunction
type: ...
params:
- param: EVENT_NAME
label: Analytics event
description: What event do you want to respond to?
type: string
default: ga_event # Specifying a default is optional.
required: true
Authentication
An authentication-triggered function runs when a user is created or deleted.
See Firebase Authentication triggers in the Cloud Functions documentation for information on writing auth-triggered functions.
Function definition (1st-gen only)
import { auth } from "firebase-functions/v1";
export const yourFunctionName = auth.user().onCreate((user, context) => {
// ...
});
export const yourFunctionName2 = auth.user().onDelete((user, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/firebase.auth/eventTypes/user.create
resource: projects/${PROJECT_ID}
- name: anotherFunction
type: ...
The following table shows how to specify each of the supported Authentication event types:
Cloud Functions event trigger | eventType |
Description |
---|---|---|
onCreate() |
providers/firebase.auth/eventTypes/user.create |
New user created |
onDelete() |
providers/firebase.auth/eventTypes/user.delete |
User deleted |
Cloud Firestore
A Cloud Firestore-triggered function runs when a document is created, updated, or deleted.
See Cloud Firestore triggers in the Cloud Functions documentation for information on writing Firestore-triggered functions.
Function definition (1st-gen only)
import { firestore } from "firebase-functions/v1";
export const yourFunctionName = firestore.document("collection/{doc_id}")
.onCreate((snapshot, context) => {
// ...
});
export const yourFunctionName2 = firestore.document("collection/{doc_id}")
.onUpdate((change, context) => {
// ...
});
export const yourFunctionName3 = firestore.document("collection/{doc_id}")
.onDelete((snapshot, context) => {
// ...
});
export const yourFunctionName4 = firestore.document("collection/{doc_id}")
.onWrite((change, context) => {
// onWrite triggers on creation, update, and deletion.
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/collection/{documentID}
- name: anotherFunction
type: ...
The following table shows how to specify each of the supported Cloud Firestore event types:
Cloud Functions event trigger | eventType |
Description |
---|---|---|
onCreate() |
providers/cloud.firestore/eventTypes/document.create |
New document created |
onDelete() |
providers/cloud.firestore/eventTypes/document.delete |
Document deleted |
onUpdate() |
providers/cloud.firestore/eventTypes/document.update |
Document updated |
onWrite() |
providers/cloud.firestore/eventTypes/document.write |
Document created, deleted, or updated |
If you want users to be able to configure the document path when they install
your extension, add a new parameter to your extension.yaml
file and reference
the parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${PROJECT_ID}/databases/(default)/documents/${YOUR_DOCUMENT_PATH}
- name: anotherFunction
type: ...
params:
- param: YOUR_DOCUMENT_PATH
label: Cloud Firestore path
description: Where do you want to watch for changes?
type: string
default: path/to/{documentID} # Specifying a default is optional.
required: true
Pub/Sub
A Pub/Sub-triggered function runs when a message is published to a specific topic.
See Pub/Sub triggers in the Cloud Functions documentation for information on writing Pub/Sub-triggered functions.
Function definition (1st-gen only)
import { pubsub } from "firebase-functions/v1";
export const yourFunctionName = pubsub.topic("topic_name").onPublish((message, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.pubsub.topic.publish
resource: projects/${PROJECT_ID}/topics/topic-name
- name: anotherFunction
type: ...
If you want users to be able to configure the Pub/Sub topic when
they install your extension, add a new parameter to your extension.yaml
file
and reference the parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.pubsub.topic.publish
resource: projects/${PROJECT_ID}/topics/${PUBSUB_TOPIC}
- name: anotherFunction
type: ...
params:
- param: PUBSUB_TOPIC
label: Pub/Sub topic
description: Which Pub/Sub topic do you want to watch for messages?
type: string
default: topic-name # Specifying a default is optional.
required: true
Realtime Database
A Realtime Database-triggered function runs when a path that matches a specified pattern is created, updated, or deleted.
See Realtime Database triggers in the Cloud Functions documentation for information on writing RTDB-triggered functions.
Function definition (1st-gen only)
import { database } from "firebase-functions/v1";
export const yourFunctionName = database.ref("path/to/{item}")
.onCreate((snapshot, context) => {
// ...
});
export const yourFunctionName2 = database.ref("path/to/{item}")
.onUpdate((change, context) => {
// ...
});
export const yourFunctionName3 = database.ref("path/to/{item}")
.onDelete((snapshot, context) => {
// ...
});
export const yourFunctionName4 = database.ref("path/to/{item}")
.onWrite((change, context) => {
// onWrite triggers on creation, update, and deletion.
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/google.firebase.database/eventTypes/ref.create
# DATABASE_INSTANCE (project's default instance) is an auto-populated
# parameter value. You can also specify an instance.
resource: projects/_/instances/${DATABASE_INSTANCE}/refs/path/to/{itemId}
- name: anotherFunction
type: ...
The following table shows how to specify each of the supported Cloud Firestore event types:
Cloud Functions event trigger | eventType |
Description |
---|---|---|
onCreate() |
providers/google.firebase.database/eventTypes/ref.create |
Data created |
onDelete() |
providers/google.firebase.database/eventTypes/ref.delete |
Data deleted |
onUpdate() |
providers/google.firebase.database/eventTypes/ref.update |
Data updated |
onWrite() |
providers/google.firebase.database/eventTypes/ref.write |
Data created, deleted, or updated |
If you want users to be able to configure the path to watch when they install
your extension, add a new parameter to your extension.yaml
file and reference
the parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: providers/google.firebase.database/eventTypes/ref.create
# DATABASE_INSTANCE (project's default instance) is an auto-populated
# parameter value. You can also specify an instance.
resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${DB_PATH}
- name: anotherFunction
type: ...
params:
- param: DB_PATH
label: Realtime Database path
description: Where do you want to watch for changes?
type: string
default: path/to/{itemId} # Specifying a default is optional.
required: true
Remote Config
A Remote Config-triggered function runs when a project's parameter template is updated.
See Remote Config triggers in the Cloud Functions documentation for information on writing Remote Config-triggered functions.
Function definition (1st-gen only)
import { remoteConfig } from "firebase-functions/v1";
export const yourFunctionName = remoteConfig.onUpdate((version, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.firebase.remoteconfig.update
resource: projects/${PROJECT_ID}
- name: anotherFunction
type: ...
Cloud Storage
A Cloud Storage-triggered function runs when an object is created, archived, or deleted, or when its metadata changes.
See Cloud Storage triggers in the Cloud Functions documentation for information on writing Storage-triggered functions.
Function definition (1st-gen only)
import { storage } from "firebase-functions/v1";
export const yourFunctionName = storage.object().onFinalize((object, context) => {
// ...
});
export const yourFunctionName2 = storage.object().onMetadataUpdate((object, context) => {
// ...
});
export const yourFunctionName3 = storage.object().onArchive((object, context) => {
// ...
});
export const yourFunctionName4 = storage.object().onDelete((object, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.storage.object.finalize
# STORAGE_BUCKET (project's default bucket) is an auto-populated
# parameter. You can also specify a bucket.
resource: projects/_/buckets/${STORAGE_BUCKET}
- name: anotherFunction
type: ...
The following table shows how to specify each of the supported Cloud Storage event types:
Cloud Functions event trigger | eventType |
Description |
---|---|---|
onFinalize() |
google.storage.object.finalize |
Object created |
onMetadataUpdate() |
google.storage.object.metadataUpdate |
Object metadata updated |
onArchive() |
google.storage.object.archive |
Object was archived |
onDelete() |
google.storage.object.delete |
Object deleted |
If you want users to be able to configure the storage bucket when they install
your extension, add a new parameter to your extension.yaml
file and reference
the parameter in your function's resource
declaration:
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.storage.object.finalize
resource: projects/_/buckets/${YOUR_BUCKET}
- name: anotherFunction
type: ...
params:
- param: YOUR_BUCKET
label: Cloud Storage bucket
description: Which bucket do you want to watch for changes?
type: selectResource
resourceType: storage.googleapis.com/Bucket
default: ${STORAGE_BUCKET} # Specifying a default is optional.
required: true
Test Lab
A Test Lab-triggered function runs when a test matrix finishes its tests.
See Firebase Test Lab triggers in the Cloud Functions documentation for information on writing Test Lab-triggered functions.
Function definition (1st-gen only)
import { testLab } from "firebase-functions/v1";
export const yourFunctionName = testLab.testMatrix().onComplete((matrix, context) => {
// ...
});
Resource declaration (extension.yaml)
resources:
- name: yourFunctionName
type: firebaseextensions.v1beta.function
properties:
eventTrigger:
eventType: google.testing.testMatrix.complete
resource: projects/${PROJECT_ID}/testMatrices/{matrixId}
- name: anotherFunction
type: ...
Crashlytics alert triggers
A Crashlytics-triggered function runs when Crashlytics publishes an alert.
See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.
Function definition (2nd-gen only)
import {
onNewFatalIssuePublished,
onNewNonfatalIssuePublished,
onNewAnrIssuePublished,
onRegressionAlertPublished,
onVelocityAlertPublished,
onStabilityDigestPublished,
} from "firebase-functions/v2/alerts/crashlytics";
export const yourFunctionName = onNewFatalIssuePublished((event) => {
// ...
});
export const yourFunctionName2 = onNewNonfatalIssuePublished((event) => {
// ...
});
export const yourFunctionName3 = onNewAnrIssuePublished((event) => {
// ...
});
export const yourFunctionName4 = onRegressionAlertPublished((event) => {
// ...
});
export const yourFunctionName5 = onVelocityAlertPublished((event) => {
// ...
});
export const yourFunctionName6 = onStabilityDigestPublished((event) => {
// ...
});
Resource declaration (extension.yaml)
apis:
- apiName: eventarc.googleapis.com
reason: Powers all events and triggers
- apiName: run.googleapis.com
reason: Powers 2nd-gen functions
resources:
- name: yourfunctionname
type: firebaseextensions.v1beta.v2function
properties:
buildConfig:
runtime: nodejs16
serviceConfig:
availableMemory: 512M
eventTrigger:
eventType: google.firebase.firebasealerts.alerts.v1.published
triggerRegion: global
eventFilters:
- attribute: alerttype
value: crashlytics.newFatalIssue
- name: anotherFunction
type: ...
You can use the following values for alerttype
crashlytics.newFatalIssue
crashlytics.newNonfatalIssue
crashlytics.regression
crashlytics.stabilityDigest
crashlytics.velocity
crashlytics.newAnrIssue
Performance Monitoring alert triggers
A Performance Monitoring-triggered function runs when Performance Monitoring publishes an alert.
See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.
Function definition (2nd-gen only)
import { onThresholdAlertPublished } from "firebase-functions/v2/alerts/performance";
export const yourFunctionName = onThresholdAlertPublished((event) => {
// ...
});
Resource declaration (extension.yaml)
apis:
- apiName: eventarc.googleapis.com
reason: Powers all events and triggers
- apiName: run.googleapis.com
reason: Powers 2nd-gen functions
resources:
- name: yourfunctionname
type: firebaseextensions.v1beta.v2function
properties:
buildConfig:
runtime: nodejs16
serviceConfig:
availableMemory: 512M
eventTrigger:
eventType: google.firebase.firebasealerts.alerts.v1.published
triggerRegion: global
eventFilters:
- attribute: alerttype
value: performance.threshold
- name: anotherFunction
type: ...
App Distribution alert triggers
A App Distribution-triggered function runs when App Distribution publishes an alert.
See Firebase Alerts triggers in the Cloud Functions documentation for information on writing alert-triggered functions.
Function definition (2nd-gen only)
import {
onNewTesterIosDevicePublished,
onInAppFeedbackPublished
} from "firebase-functions/v2/alerts/appDistribution";
export const yourFunctionName = onNewTesterIosDevicePublished((event) => {
// ...
});
export const yourFunctionName2 = onInAppFeedbackPublished((event) => {
// ...
});
Resource declaration (extension.yaml)
apis:
- apiName: eventarc.googleapis.com
reason: Powers all events and triggers
- apiName: run.googleapis.com
reason: Powers 2nd-gen functions
resources:
- name: yourfunctionname
type: firebaseextensions.v1beta.v2function
properties:
buildConfig:
runtime: nodejs16
serviceConfig:
availableMemory: 512M
eventTrigger:
eventType: google.firebase.firebasealerts.alerts.v1.published
triggerRegion: global
eventFilters:
- attribute: alerttype
value: appDistribution.inAppFeedback
- name: anotherFunction
type: ...
You can use the following values for alerttype
appDistribution.newTesterIosDevice
appDistribution.inAppFeedback
Custom event triggers (Eventarc)
An Eventarc-triggered function runs when a specific event type is published to a specific channel.
See Create and handle custom event triggers in the Cloud Functions documentation for information on writing Eventarc-triggered functions.
You can also publish events from your extensions to give users a way to insert custom logic into your extension. See Use developer-provided custom logic in an extension.
Function definition (2nd-gen only)
import { onCustomEventPublished } from "firebase-functions/v2/eventarc";
export const yourFunctionName = onCustomEventPublished((event) => {
// ...
});
Resource declaration (extension.yaml)
apis:
- apiName: eventarc.googleapis.com
reason: Powers all events and triggers
- apiName: run.googleapis.com
reason: Powers 2nd-gen functions
resources:
- name: yourfunctionname
type: firebaseextensions.v1beta.v2function
properties:
# LOCATION is a user-configured parameter value specified by the user
# during installation.
location: ${param:LOCATION}
buildConfig:
runtime: nodejs16
serviceConfig:
availableMemory: 512M
timeoutSeconds: 60
eventTrigger:
eventType: firebase.extensions.storage-resize-images.v1.complete
channel: projects/${param:PROJECT_ID}/locations/us-central1/channels/firebase
- name: anotherFunction
type: ...
The channel must already exist when your extension is installed. For example, if you depend on custom events from another extension that creates the channel, instruct your users to install that extension first.
The above example would create a custom event trigger for the "default" Firebase
channel in us-central1
region. You can make the channel name and region
customizable by using parameters. For example:
params:
- param: EVENTARC_CHANNEL_NAME
label: Eventarc channel name
description: What is the name of the Eventarc channel.
default: firebase
type: string
required: true
resources:
- name: yourfunctionname
type: firebaseextensions.v1beta.v2function
properties:
location: ${param:LOCATION}
eventTrigger:
eventType: firebase.extensions.storage-resize-images.v1.complete
channel: projects/${param:PROJECT_ID}/locations/${param:LOCATION}/channels/${param:EVENTARC_CHANNEL_NAME}