Dynamic landing pages with Firebase

To accomplish some marketing idea we recently wanted to test, we faced the problem how to quickly launch multiple landing pages with dynamic content. By multiple I mean 1000+ and by dynamic content I mean not only 2-3 values (like user/customer name) but 20-40 different variables. Of course there’s probably a milion or so possible solutions for this issue, but here I present the one I’ve chosen and which has a few advantages. You don’t have to host it, it’s free (at least before hitting some higher traffic), it can be made fully on the client side (no backend development is required) and finally it can be launched in few hours.

First I’ve looked at online landing page providers. A lot of them don’t provide dynamic landing pages at all, so we’d need to create some static content using their services. If we think about 1000+ pages it’d be horrible cost. There are some landing page providers who support dynamic content, but the variables need to be injected using GET params. This may work well with 2-3 variables, but not with 40. Moreover it’s still dangerous, because your competition can generate URL-s to generate fake landing pages that can put you to shame. So, the most safe way is to keep the dynamic content on the server side.

Before we delved into our custom solution I’ve remembered that about two years ago we evaluated for some different purposes Firebase, which now became Google product. This is a document database (in JSON format) hosted in the cloud and accessible purely from the client side. The additional and new for me feature is that they also provide hosting. And the best thing when you use both functions is that sites hosted from their hosting are automatically authenticated to the database, so you don’t need to reveal credentials in your javascript code. This is everything I need to launch dynamic landing pages.

Landing

It’s quite easy to start with this technology using npm. However, let’s start from our HTML template with landing content:

Having this in index.html file as the only file in the project (in public/ subfolder), after creating Firebase account and setting up a project in Firebase Console you can setup initial environment using:

npm install -g firebase-tools
firebase login
firebase init

Now you can serve your project locally using temporary HTTP server with:

firebase serve

And you can deploy project to the production environment with:

firebase deploy

Database

Now in Database section in Firebase Console you need to create database. I assumed our dynamic data will be configured in a simple JSON structure:

You can insert data to Firebase in few different ways. For development purposes you can just input few nodes manually using their web interface. You can prepare JSON somewhere else and import it. Finally you can add new nodes to database using Firebase API. The latter one is especially great, because this means you can create new landings dynamically, for example from your CRM.

The only caveat is that by default the database is available for clients only after authentication. Here we want to make it available for read without it and we need to change authentication settings on database Rules tab to the following:

{
"rules": {
".read": "true",
".write": "auth != null"
}
}

Client controller

Finally we need some javascript to glue everything. I assumed that we have everything hosted on some domain http://landing.com and we want to have separate landings accesible under http://landing.com/XXX URL-s, where XXX corresponds to the node in the database (eg. company1, company2 from the example).

I used angularjs (version 1) to accomplish this task and our landing template changes in the following way:

The only modifications, besides adding Firebase code (which is generated for copy&paste in Firebase Console) is adding ng-* attributes to html and body, including angularjs and angularfire (AngularJS bindings for Firebase) libs and of course adding our small AppCtrl controller in js/app.js:

After database loading, what is done in the promise, I check if the node has full_name property - because I didn’t find any other way to check if node exists in database or not. If property doesn’t exist it means that the node doesn’t exist, what results in redirecting back to our main company website. Otherwise the landing is rendered and the data is injected into template using {{company.xxx}} placeholders.