Skip to contentSkip to navigationSkip to topbar
On this page

Send Abandoned Cart Reminders with SendGrid


Use the Send Abandoned Cart Reminders with SendGrid Firebase extension(link takes you to an external page) 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 SendGrid API. The information in the document is sent as the template data for a dynamic transactional email.


How it works

how-it-works page anchor

This extension uses the following flow to send Abandoned Cart Reminders:

  1. You create a new document in the cartFirebase collection. The document should either have the same ID as your customer in Firebase Auth or it should have a property userId which is the same as your customer in Firebase Auth. This document represents the Customer's cart, and typically contains an array property with items, for example.

  2. When you create the cart document or update properties on the cart, the extension will update a property called lastUpdated, giving the extension a sense of whether the cart is abandoned.

  3. A function will regularly check the collection of cart documents to determine if the cart has been abandoned

  4. If the lastUpdated metadata property indicates that the cart was abandoned (as determined by an interval you can define during setup), it will add a document to an email collection. This tells the extension that it needs to email the customer, prompting them to return to their cart

    1. The metadata will be updated to indicate that an email has been sent and/or an error has occurred while trying to send an email
  5. Otherwise, the extension determines that the cart isn't abandoned and will ignore it until the document is removed (indicating that the customer has checked out)


How to set up Abandoned Cart Reminders

how-to-set-up-abandoned-cart-reminders page anchor

Requirements

requirements page anchor

Before installing this extension, make sure:

Set up a composite Firestore index

set-up-a-composite-firestore-index page anchor

This extension requires a composite Firestore index. You can add the index in the Firebase console or by the command line.

Method 1: Indexes in the Firebase Console

method-1-indexes-in-the-firebase-console page anchor
  1. Go to the Cloud Firestore section of the Firebase console(link takes you to an external page)

  2. Go to the Indexes tab and click Add Index

  3. Enter the collection name for your cart collection

  4. Add the following fields to the index:

    • metadata.emailSent - Ascending
    • metadata.error - Ascending
    • metadata.lastUpdated - Ascending
  5. Set the Query scopes to Collection

  6. Click Create

Method 2: Indexes with the Firebase CLI

method-2-indexes-with-the-firebase-cli page anchor
  1. In your Firebase project, open your index configuration file, with default filename firestore.indexes.json

  2. Add the following object to the indexes array:

    1
    {
    2
    "collectionGroup": "cart",
    3
    "queryScope": "COLLECTION",
    4
    "fields": [
    5
    { "fieldPath": "metadata.emailSent", "order": "ASCENDING" },
    6
    { "fieldPath": "metadata.error", "order": "ASCENDING" },
    7
    { "fieldPath": "metadata.lastUpdated", "order": "ASCENDING" }
    8
    ]
    9
    }

    The collectionGroup name should be the collection name for your cart collection.

  3. Deploy your index configuration with the firebase deploy command. If you only want to deploy indexes, add the --only firestore:indexes flag.

Due to the nature of the extension, it's difficult to see the full effects of this extension immediately. Here's what you can do:

  1. Go to your Cloud Firestore dashboard(link takes you to an external page) in the Firebase console.

  2. If it doesn't already exist, create the cart collection you specified during installation: ${param:CART_COLLECTION}

  3. Add a document with an items field containing some products:

    1
    {
    2
    "items": [{ "name": "Test product 1", "price": "$9.99" }]
    3
    }
  4. In a few seconds, you will see a metadata field appear in the document. The field will contain a lastUpdated property that will be set to the current time

  5. If you update any properties outside the metadata property, you will see the metadata.lastUpdated property update shortly after

  6. Once ${param:ABANDONED_TIMEOUT} minutes have passed, the cart will be updated again and a new document will be placed in the ${param:EMAIL_COLLECTION} collection

  7. In a few seconds, you will see a delivery field appear on the new document in the ${param:EMAIL_COLLECTION} collection. The field will update as the extension processes the message and sends it via the SendGrid API


Use the Abandoned Cart Reminders Extension

use-the-abandoned-cart-reminders-extension page anchor

Using the extension begins with tracking your customers' carts. A shopping cart should be represented as a single document in the collection per cart. How you store items in the document is up to you. Typically, a cart will include an array property called items, which contains information about each of the items in the cart.

The document should also have a reference to a Firebase Authentication(link takes you to an external page) 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.

You can configure the period with which the extension checks the cart by updating the CART_CHECK_INTERVAL, which should be declared in extension.yaml using cron.yaml syntax(link takes you to an external page).

A cart document must fulfill the following conditions before it triggers an abandoned cart reminder:

  • the metadata.lastUpdated timestamp should be older than the configurable ABANDONED_TIMEOUT time in minutes
  • the metadata.emailSent Boolean property should be false
  • 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(link takes you to an external page). You can also set a DEFAULT_REPLY_TO email.

Furthermore, you can send an email at any time by adding a document to the EMAIL_COLLECTION with a to email address and a dynamicTemplateData property.

1
admin.firestore().collection('cart_emails').add({
2
to: 'example@example.com',
3
dynamicTemplateData: {
4
name: "Example"
5
}
6
});
Need further assistance?

On GitHub, you can take a look at the source code, or read through the existing issues to see if somebody else had a similar problem. If you're still stuck, feel free to create a pull request or open an issue yourself!

Check out the GitHub repo(link takes you to an external page)

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.