Gonçalo Palma
August 1, 2023

Firebase Extensions – Shorten URLs

Photo by Muhamad Guntur on Unsplash

Sharing is one of the most common features in modern web and mobile applications. It allows us to show a social media post or a photograph we took to a friend, share the planning for an upcoming business travel with our company, or even send that item from an e-commerce website to Santa to have a PS5 finally. To do so, we copy the URL for that specific website (or use the Share function on our devices), and we send it via different outlets - social media, messaging apps, snail mail, or others so that other people can click on it and see what we wanted to share.

The problem with overcomplicated URLs

If we look at the URLs that we are sharing, we see that, as with many things, they come in different shapes and formats. They can be just a URL that links to the homepage of a blog:

https://gpalma.pt

Or they can have different paths and query parameters that make the URL very long and, sometimes, illegible at first look:

https://www.google.pt/search?q=gpalma&sxsrf=APwXEdeCQLFcPi9AX3B4e38Zac8DeUlMdw%3A1684584069756&source=hp&ei=hbZoZKLfK7ubkdUPrJ-L4As&iflsig=AOEireoAAAAAZGjElUPo1owxQ_FzOHwvfXscfUZPgnz9&ved=0ahUKEwjitcfY7IP_AhW7TaQEHazPArwQ4dUDCAk&uact=5&oq=gpalma&gs_lcp=Cgdnd3Mtd2l6EAMyBwguEIAEEAoyBwgAEIAEEAoyBwgAEIAEEAoyBwgAEIAEEAoyBwgAEIAEEAoyBwgAEIAEEAoyBwgAEIAEEAoyCgguEIAEENQCEAoyBwgAEIAEEAoyBwguEIAEEAo6BwgjEIoFECc6BQgAEIAEOgsILhCABBDHARDRAzoKCC4Q1AIQgAQQCjoNCC4QgAQQxwEQrwEQClAAWIAEYOwIaABwAHgAgAGuAYgB4gaSAQMwLjaYAQCgAQE&sclient=gws-wiz

Suppose we share this second link via social media or messaging. In that case, It will make the message/post very long, with the chance of the person missing the first few sentences we shared before pasting the URL, or worse, it goes beyond the character limit of the platform we are using.

Let’s look at it from another perspective - what if we store URLs in our application’s database? Maybe we are generating a URL for a user’s shopping cart that makes heavy use of different path and query parameters to specify the current state of the operation:

https://my-amazing-shopping-app.com/shop/cart?id=b80b3d15-ae4f-456b-89ce-126fd352dbd9&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&theme=dark&date=1684574524886&ref=megabananaz003

As per our app architecture, we update the user’s object on our database with this URL each time a new cart operation is performed. This example URL has 296 bytes, which means that if we have 10.000 users, we will have 2,96 MB of data in this field. What if we also allow our users to save a list of external websites in their preferences? In that case, we don’t know how many characters we will have per entry, meaning we can’t even calculate the total amount of data and potentially the cost of storing that data.

Reducing our URL size with bit.ly

In both cases, either sharing externally or storing in our app’s database, we could make our life’s easier by sanitizing and shortening the URLs we use. This means that instead of using the original URL, which has an undetermined number of characters, we would build a URL with a prefix, and a short code that would redirect to the original URL, such as gp.com/XYZ123, with gp.com being the prefix and XYZ123 the unique code that points to a specific URL.

Fortunately, services like bit.ly do this for us automatically, where the previously shared URL that was stored in the database is shortened to https://bit.ly/3IrEbFA, meaning that in our database it would change the total byte size from 296 to 22, reducing it by 93%, and the number of characters to 22, making it much easier to share in any application.

In order to create our bit.ly shortened URLs, we just need to go to the website, sign up and click on the “Create New” button on the left navigation drawer.

BitLy Menu

Then, we can customize our link as needed, by providing the URL, a back-half to make the link more personal and, if we upgrade to premium, we can add a custom domain to use instead of bit.ly.

Creating New URL

The previous example creates the URL bit.ly/gpalma that redirects to https://a-really-long-url.io/with-path?and=queryParameters. Moreover, if we check our URL in the dashboard, we can see different Analytics such as the number of clicks, the location, and where it was clicked.

URL Configuration

If we want to implement this feature in our application, we could head straight to bit.ly’s developer documentation and see how we can make it work. However, if we are using Firebase, there’s an easier way to achieve it - via Firebase Extensions, which allows us to quickly add features to our Firebase application directly from an Extensions Hub, in the same way, that we would add a pub.dev library to our Flutter project. Let’s see how we can make it work in an existing Firebase project.

The project - Wall of Sharing

The “Wall Of Sharing” app allows users to share their work by creating a new post that is composed of a title and a URL.

App Intro

As a starting point to add the extension, we can use this Zapp.run project with the Wall of Sharing Flutter project:

We need to change the firebase_options.dart file to use our Firebase project’s configuration, and we can run and test our Firebase Extensions.

Firebase Firestore is used to save this data in a collection called posts, and when creating a new entry, we only send the title and url parameters using the following Dart function:

  Future<void> _createPost(String title, String url) async {
    await FirebaseFirestore.instance.collection('posts').add({
      'title': title,
      'url': url,
    });
  }

What we would want, ideally, is that when the data reaches Firebase, a new property called shortUrl would be created in this document with the [bit.ly] URL. To create this, we would have to create and manage a new Firebase Cloud Function with a specific Firestore Trigger that would use the bit.ly API to retrieve a new shortened URL to update the document with the new property. However, this would mean adding another codebase to our existing project that we would need to maintain, test and manage. Thankfully, the Firestore Shorten URLs function, created by the Firebase team, does precisely that for us.

Adding the bit.ly Firebase Extension to our project

If we navigate to the Firestore section of our project, we see a new tab at the top (with a NEW badge on the right) with the title “Extensions”.

Cloud Firestore

Clicking on it displays a page with a brief explanation of Firebase Extensions and a collection of the most used ones.

Adding Extension

In our case, we want to click on “Explore Extensions Marketplace”, which would be the same as navigating to extensions.dev, where we can search for our URL shortening Extension.

Searching for new extensions

The details page of the Extension page has all the information we need to get started, including:

Shorten Firebase URLs homepage

From the Getting Started section, we already have a checklist of items we need to tick before implementing this extension in our project:

For the last requirement, as soon as we have the account created for bit.ly, we can navigate to the settings page and click on Developer Settings > API where we are able to generate a new Access Token.

API Token

We can return to the Extension’s detail page, where we can check the Configurable Parameters section where we see what we can customize in this extension:

Firebase Extension Configurable Parameters

Here we can see that we need to specify the access token, created in the previous step, and the Firestore collection and sets of fields that are going to be manipulated, which in our case is going to be:

To install this Extension, we can click on the “Install in Firebase Console” button, that will first show us the homepage of all of our Firebase Projects, where we can specify to which project we want to add the extension.

Choosing Firebase Project

After selecting our project, we are presented with the Firebase Extension installation page, where we are first prompted to set up the billing to upgrade our project to Blaze if we haven’t done that beforehand.

Installing Extension 1

Then, we can review what are the resources that are going to be created, in this case, a Cloud Function called fsurlshortner and a Cloud Secret Manager secret for our bit.ly access token.

Installing Extensions 2

Next, we review the list of all the Google Cloud Services that need to be enabled in our project, as it was stipulated in the Extension’s description page.

Installing Extensions 3

Since our project needs to manipulate Firestore data and manage Secrets, we will need to review and provide any necessary permission.

Installing Extensions 4

Finally, we can configure our Extension with the parameters we’ve discussed before: the access token, collection’s path, original URL field name and the field name where the extension will store the shortened URL. Since it’s all done inside a Cloud function, we also need to specify its location.

Installing Extensions 5

As soon as we click on “Install extension”, we see a page with the list of all the installed extensions and where we see the estimated time needed to install this new Extension.

Installing Extensions 6

After the necessary time to install it, we get the green light and we can start using it in our application.

Installing Extensions 7

To test it, we just need to create a new post and see if the shortUrl parameter is present in the newly created document.

Firestore Outcome

As expected, after a brief moment, the document is updated with the new parameter, which we can then display in our application. However, we want to keep both the legacy posts, without the shortened URL, and the posts with a shortened URL. For that to happen, we just need to conditionally show the shortened URL, if available, and navigate to the specified web page:

TextSpan(
  text: snapshot.data![index].shortUrl ??
	  snapshot.data![index].url,
  mouseCursor: SystemMouseCursors.click,
  recognizer: TapGestureRecognizer()
	..onTap = () => launchUrl(
		  Uri.parse(
			snapshot.data![index].shortUrl ??
	  snapshot.data![index].url,
		  ),
		),
),

This effectively displays both posts in our Wall of Sharing:

App Outcome

Conclusion

We want to shorten URLs in our apps for multiple reasons. We may want it to be easier for users to share in different social media apps or to keep the SMS message we send short so we don’t have to pay extra. Whatever the reason, bit.ly not only makes it easy to reduce our URLs but also provides us with some analytics tools that can give us invaluable insights into our app.

And as we saw, this feature can be quickly embedded into our project by using a Firebase Extension - we need to tinker with some initial configurations, and the Extension will reduce the URLs we provide to it via Firestore. This effectively shortens the development time of this feature to minutes instead of days of setting up Cloud Functions and tinkering with bit.ly’s API.

This example serves as a perfect showcase of the power and ease of use of Firebase Extensions. Stay tuned to learn about more Extensions in the future!


Originally published at Invertase - Firebase Extensions – Shorten URLs.

Want to get the latest articles and news? Subscribe to the newsletter here 👇

Diving Into Flutter

In Diving into Flutter we will discover the Flutter Framework, bit by bit.

From the BuildContext, to pubspec files, going through exotic backend solutions, there won't be a stone left unturned.

Each week I'll also share one or two links for interesting resources I found around the Web

And for other articles, check the rest of the blog! Blog - Gonçalo Palma

Want to get the latest articles and news? Subscribe to Diving Into Flutter

Hey! I'm Gonçalo Palma! 👋

I often share Deep Diving articles on Flutter 💙