Author: Twilio (https://www.twilio.com)
Description: Watches a cart collection keeping track of the last updated time of a cart object. When it is over a certain period, send the user an email based on a SendGrid Dynamic Template.
Details: Use this extension to automate sending an email reminder to users about items they left in their shopping cart.
This extension will watch the documents added to a specified Cloud Firestore collection. For each document the extension records the last updated time of the document. Then, when the last updated time goes beyond a configurable threshold, the information in the document is copied to a new collection which triggers an email using the Twilio SendGrid API. The information in the document is sent as the template data for a dynamic transactional email.
Before installing this extension, make sure:
- You have set up a Cloud Firestore database in your Firebase project
- You have set up Firebase Authentication in your Firebase project
- You have signed up for a Twilio SendGrid Marketing Campaigns account
- You have created a SendGrid API Key with access to send emails
- You have verified a single sender email address or set up domain authentication with SendGrid
- You have a dynamic transactional template setup with which to send emails
This extension requires a composite Firestore index. You can add the index in the Firebase console or by the command line.
- Go to the Cloud Firestore section of the Firebase console
- Go to the Indexes tab and click Add Index
- Enter the collection name for your cart collection
- Add the following fields to the index:
metadata.emailSent
- Ascendingmetadata.error
- Ascendingmetadata.lastUpdated
- Ascending
- Set the Query scopes to Collection
- Click Create
-
In your Firebase project, open your index configuration file, with default filename
firestore.indexes.json
-
Add the following object to the
indexes
array:{ "collectionGroup": "cart", "queryScope": "COLLECTION", "fields": [ { "fieldPath": "metadata.emailSent", "order": "ASCENDING" }, { "fieldPath": "metadata.error", "order": "ASCENDING" }, { "fieldPath": "metadata.lastUpdated", "order": "ASCENDING" } ] }
The
collectionGroup
name should be the collection name for your cart collection. -
Deploy your index configuration with the
firebase deploy
command. If you only want to deploy indexes, add the--only firestore:indexes
flag.
A shopping cart should be implemented as a document per cart. How you store items in the document is up to you, but an array property called items
containing information about each of the items in the cart is typical. The document should also have a reference to a Firebase Authentication User, either the cart document ID should match the user ID or there should be a userId
property on the document. When you create the cart document or update properties on the cart document, the extension will update a metadata.lastUpdated
timestamp.
A function runs periodically to determine whether any carts are abandoned and should be emailed. You can configure the period with the CART_CHECK_INTERVAL
using cron.yaml syntax.
There are a few conditions that a cart document must fulfill before it is processed to the next stage:
- the
metadata.lastUpdated
timestamp should be older than the configurableABANDONED_TIMEOUT
time in minutes - the
metadata.emailSent
boolean property should befalse
- there should be no errors present in the
metadata.error
property
If all of these conditions are met, then the extension will attempt to load the user data using the userId
property or the document's ID. If the user doesn't have an email address, an error will be recorded. If the user has an email address then a document will be created in the EMAIL_COLLECTION
. The document will include the user email and a property for dynamicTemplateData
consisting of the contents of the user's cart and a user
property including the user's email
and displayName
if present. This dynamicTemplateData
is used to fill in the fields in a SendGrid dynamic email template.
When a document is added to the EMAIL_COLLECTION
the contents are queued up to be emailed using the Twilio SendGrid API. All the information from the cart document is added as dynamic template data for the email. You can configure a DEFAULT_TEMPLATE_ID
which is the ID of a SendGrid dynamic template.
You can create dynamic transactional templates in the SendGrid dashboard. SendGrid Templates use Handlebars to render dynamic data into the email.
You also need to configure your DEFAULT_FROM
to be an email address that you have verified with SendGrid as either a single sender or via domain authentication. You can also set a DEFAULT_REPLY_TO
email.
You can trigger an email to be sent at any time by added a document to the EMAIL_COLLECTION
with a to
email address and a dynamicTemplateData
property.
admin.firestore().collection('cart_emails').add({
to: '[email protected]',
dynamicTemplateData: {
name: "Example"
}
});
To install an extension, your project must be on the Blaze (pay as you go) plan
- You will be charged a small amount (typically around $0.01/month) for the Firebase resources required by this extension (even if it is not used).
- This extension uses other Firebase and Google Cloud Platform services, which have associated charges if you exceed the service’s free tier:
- Cloud Firestore
- Firebase Authentication
- Cloud Functions (Node.js 10+ runtime. See FAQs)
- Cloud Secret Manager
Usage of this extension also requires you to have a Twilio SendGrid account and credentials in order to use the Twilio SendGrid API for marketing campaigns. You are responsible for any associated costs with your usage of Twilio SendGrid.
Configuration Parameters:
-
Cloud Functions location: Where do you want to deploy the functions created for this extension? You usually want a location close to your database. For help selecting a location, refer to the location selection guide.
-
SendGrid API Key: What is your SendGrid API key? Make sure it has permission to send emails.
-
Email documents collection: What is the path to the collection that contains the documents used to build and send the emails?
-
Default from email address: What is the default email address to send the emails from?
-
Default email to set as reply-to: What is the default email address to set as the email reply-to field?
-
Default email dynamic template ID: What is the SendGrid Dynamic Template ID that you want to use by default
-
The collection your shopping cart is stored in: What is is the collection that this extension should observe in order to calculate whether a cart has been abandoned?
-
Time in minutes: What is the amount of time in minutes a cart is inactive before this extension will send them an email?
-
Schedule for the check for abandoned carts: On what schedule should the cart collection be checked for abandoned carts? You can provide this in App Engine cron.yaml syntax.
Cloud Functions:
-
processEmailQueue: Processes document changes in the specified Cloud Firestore collection, delivers emails, and updates the document with delivery status information.
-
processCartUpdate: Processes changes to documents in the collection that represent a shopping cart, adding metadata about the document, specifically a last updated field that can be used to determine whether the cart has been abandoned.
-
processCartCheck: Runs periodically to check any carts that have been abandoned. If they have adds the details from the cart to the email collection so that an email can be sent out.
Access Required:
This extension will operate with the following project IAM roles:
-
datastore.user (Reason: Allows this extension to access Cloud Firestore to read and process added message documents.)
-
firebaseauth.viewer (Reason: Allows this extension to access Firebase Auth to read user information.)