Hi, everyone. I’m Kara, and I’m the product manager for Firebase Extensions.
And this is Iman, the engineering manager for Firebase Extentions.
And we’re going to build a retail app with extensions.
Building an app can be complicated.
It usually involves integrating many new APIs,
writing code, and figuring out how to make everything work together.
Firebase Extensions are here to help.
The prepackaged bundles of code allow you to automate common development tasks
and add new functionality to your app much faster.
Extensions make it easy to integrate retail functionality
so you can spend more time working on your app’s special sauce.
We’re excited to announce we’ve launched several new and updated extensions.
Here’s a partial list of what we’re going to be using.
Let’s get started.
Now we’re really into coffee recently and have decided to build an app to sell
our favorite coffee supplies, introducing Kara’s Coffee.
The source code for this app is available open source on GitHub.
So feel free to follow along.
Here’s what we’ll be covering.
Search: I’ll need to implement search
so users can find the product they want to buy.
Shopping cart: I’ll need a shopping cart so users can track
the items they intend to buy.
Payments: I’ll need a way to process payment from a user
when they do end up buying.
Shipping: I’ll need some way to ship the product to the user
and charge them for shipping.
This includes validating a shipping address, calculating a shipping rate,
charging for shipping and generating a shipping label.
User communications: I’ll need to update the user on the status of our items.
Let’s start with search.
Indexing your database
so you can implement product search is important.
Luckily, I found the Search with Algolia extension on the Firebase website.
This extension listens to updates in my specified Cloud Firestore collection
and automatically indexes them in Algolia.
Because I can use the Algolia client’s SDK here,
the filtering even happens in real time.
We wanna focus on some of the other parts of building the app.
For more details,
here’s a longer video on how to use the Algolia extension to build out search.
Now, a shopping cart is an important part of an app
which tracks the items that a user intends to buy.
You can implement anything you want here. In this case, we happen to use this schema.
Now that I have a cart, let’s go check out!
Luckily, Stripe is here to help.
Here I have a Payments with Stripe extension already installed.
I configured it to work with my app.
Note that I specify my products and my customer’s collection.
This keeps in sync with my product SKUs and customer status in Stripe.
Now, this extension is driven off of a Stripe Checkout product,
a prebuilt hosted payments page.
Starting today, the extension supports one-time payments, subscriptions,
promotion codes and dynamic tax rates all out of the box.
The core thing driving this extension is a checkout session’s collection
stored under the customer document.
When I click on “Place Order,”
we create a checkout_session object in Firestore,
and Stripe triggers to call the Stripe API and passes it the checkout session data.
That generates a URL to the Checkout Payment page,
which you’ll see here.
I enter my credit card.
If it succeeds, then this payment collection gets created automatically
by the Stripe extension in my Firestore collection
and includes payment data.
And that’s not all. You heard it here first!
There’s a completely new feature from Stripe making it possible
to turn on new payment methods with just one click in the Stripe dashboard.
This allows me to add over 15 different payment methods, including wallets,
bank redirects and buy now, pay later products with no additional code.
Now, how did I get this working with my client code?
Great news! We now have an SDK for this extension.
It’s as simple as adding the dependency to my project
and importing it in my code like this.
And here’s all the code I need to write to create the checkout session.
But wait! I forgot about shipping.
I need to figure out how much that costs and charge a user for that too.
Iman, can you help me out?
Sure, Kara, of course.
Our coffee store needs to deliver real coffee products to users all across the world.
For this, I need to validate the address,
calculate the shipping rate for the products in the shopping cart,
collect payment from the user via the Stripe Checkout page
and generate a shipping label after verifying the payment has succeeded.
Ideally, in the end, I would like to notify the users of updates of their package
along the way as it gets shipped from my warehouse to their home.
So, to validate addresses, I first installed a Validate Address with ShipEngine extension.
This triggers on changes to a collection in Firestore,
reads the address, queries the ShipEngine API to verify the address,
and updates the document in place with verification status
and a normalized address returned from ShipEngine.
I go to the extension and click on “Install.”
For Billing, I can take a look at potential billing
from ShipEngine, Cloud Functions and Secret Manager.
Here’s a prewritten function the extension would pull into my project.
This extension also enables a Secret Manager API for my project
and creates and manages secrets related to the extension.
I review the access granted to the extension.
This permission gives the extension access to my Cloud Firestore
so that it can read, write and process added documents.
And now it’s time to configure the parameters.
The configuration includes the location to deploy the function,
the ShipEngine API key,
the collection where the input address is stored,
the validation key to store the result in, and an input schema.
This schema allows you to customize how your data schema
is mapped to ShipEngine API schema.
You can read more about this in the extension’s documentation.
Now, when I enter a new address,
I store this in the previously specified Firestore collection,
and then the Validate Address with ShipEngine extension
kicks off and validates it.
Now I can select my validated address and get the shipping rate for that address.
To do this, I install Calculate Shipping Rates with ShipEngine extension.
And this extension can trigger via an HTTPS end point,
which I'll use to send a validated address
and product information to get back shipping rates by different carriers.
Let's select the shipping rate.
I have to include the selected shipping rates into Stipe’s checkout sessions
so Stripe can collect the payment.
We add the shipping information as a line item to the checkout session.
I will do this via the Stripe client SDK, which makes it pretty easy and intuitive.
Now I’ve solved Kara’s problem.
The amount to pay for shipping is calculated and shown to the user.
Then when the user clicks “Checkout,”
we create a new checkout session document and a user can pay for the product.
When payment succeeds,
a new payment document is created in the payments collection,
which indicates a user has completed payment of the Stripe checkout session.
The document contains all the information we need about the purchase,
which includes all the line items added previously by us.
Here’s what we’ve done.
I have shipping rates figured out and payment collected by Stripe.
But it’s really hard to ship something
without actually getting everything prepped with a shipping company.
Luckily, the Purchase Shipping Labels with ShipEngine extension
will create a shipping label for me.
This extension will trigger when a new document is added to a collection,
here, the payment collection Stripe uses,
and we’ll look for shipping information in the payment record.
The shipping label will be created from our shipping information
and written back to the same document in Firestore.
Here I can see the shipping label under the shipping label key,
which links to a PDF file containing the shipping label information.
Now, all I need is a printer and a box to get my products delivered to my customers.
So I’m done with shipping and payments integration.
My app can calculate shipping rates,
accept payments, and generate shipping labels so I can send them to my customers.
Next, I would like to keep the users updated on their package status.
The Track Shipping Labels with ShipEngine extension
will write the tracking information into the collection provided.
This will include when the package gets shipped from the warehouse
and important steps in its journey to my customer’s address.
What’s more, I can even keep my customer updated on their package ETA.
For this, I want to connect the Send Messages with Twilio extension
to ShipEngine’s Tracking Updates.
I create a custom Cloud Function
that triggers off the Tracking Updates collection,
constructs a nice custom message for that user,
and writes it to a messages collection.
If I install the Send Messages with Twilio extension
and set it to trigger off this collection,
this extension will deliver my custom-crafted messages through Twilio’s API.
All right, now I fully set up a working shopping cart
using Firestore, Stripe’s simple Checkout and web SDK,
ShipEngine’s and Twilio’s extensions.
In the process, I learned one of the many ways
to get extensions working with each other to build more sophisticated applications,
dealing less with integration code and more with my application logic.
Kara, I think I got shipping working for your app.
Wow! Thanks Iman.
You did so much more than just solve my shipping rates problem.
Now let’s say I want to make sure more users get to that checkout step.
Another bonus extension Twilio has launched
is an extension called Send Abandoned Cart Reminders with SendGrid.
Abandoned shopping carts are when users leave the checkout process before completion.
I’d like to send reminders to these users of the items in their cart
and bring them back to complete their purchase.
Here you see the configuration used in the install.
This extension uses scheduled functions to check on a status of a shopping cart,
and after a certain amount of time,
sends an email reminder through SendGrid to the user.
Installation is pretty straightforward.
You specify the shopping cart collection and the timeout,
along with email template information similar to our trigger email extension.
And here it is in my email now. Look at all these items I left behind!
Together, we solve all parts of getting a fully working retail app together.
We've set up search using Algolia, put together a shopping cart,
handle payments together a shipping costs,
a shipping labels and even set up tracking updates are sent to the customers.
But this is all just the tip of the iceberg. There's so much more to building an app.
The Kara’s Coffee app actually uses over 17 extensions.
If you take a look at the code in Kara’s Coffee open-source GitHub repo,
most of the code is for the web app itself.
To make it extra easy to take this for a spin yourself,
we’ve included a manifest of all the extensions used,
and there are configurations as part of that same open-source repo.
The cool thing is that each one of the extensions will work by itself
and together with each other.
So you can choose what parts of the app to build using extensions.
Extensions made it super easy for me to add all this functionality in less than a week,
so I can focus on what matters most.
Now, to figure out which is the best French press.