A Serverless Blog for Business

When getting ready to launch a business online there are a million things to do, and creating the landing page or blog are often underestimated. In this post we walk through all the steps you need to go through to get one ready to handle any traffic you can throw at it as well as let you (re)connect with the audience you build.

Why Serverless?

In order to meet our goal of being able to handle traffic from the front page of Reddit, we need a hosting platform that can scale to extreme amounts of traffic. This is also a new business so keeping cost under control is a must. Enter serverless computing. Serverless cuts cost on two fronts, first you pay only for what you use, and second your team is freed for managing the servers that run your business. Serverless is on the verge of opening an entirely new startup ecosystem TODO: Ref, one that you would be smart to leverage from the start. There are many platforms you can choose to run a serverless stack, but in this post we use AWS. Most of the things we cover are applicable no matter where you choose to deploy, though some of the tools used are specific to AWS but can be replicated on other platforms.

Deploying the Blog

Let’s get started! This section walks through creating the accounts needed and setting up the tools to deploy fast and scalable blog.

Create an AWS account

We will need a place to host the blog, and since AWS is the platform we are using its time to create an account. Follow the steps listed in the article below.
https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/

Installing Node.js, Serverless framework, and Hexo

Next we need to install our tool chain. The tools we are using all built on Node.js.

Node.js
Node is simple to install, but the Node world moves very fast. Having a simple way to manage which version you are using makes life much simpler in the long run. If you are developing on a Mac or Linux I strongly suggest using NVM (Node Version Manager) to install Node.
It’s available using home brew on Macs. #TODO, home brew is unsupported…

1
brew install nvm

or follow the instructions on their home page.
https://github.com/creationix/nvm

Once nvm is installed install node by running

1
nvm install 'lts/*'

to install the latest LTS version on Node. #TODO, nvm use after opening a new terminal.

Serverless framework

1
npm install -g serverless

Yep, that’s it. For more see their Getting Started Guide

Hexo

1
npm install -g hexo-cli

A little more information can be found on their Getting Started Page

Custom domain and free SSL

AWS Certificate Manager allows you to create free certificates for any domain that can be used when serving content from AWS services like CloudFront. There are three different options depending on your situation:

  1. Managing the domain with Route 53
    Route 53 is the AWS DNS provider. If the domain is using Route 53 DNS, then AWS will be able to verify ownership of your domain automatically (assuming it is managed by the same AWS account).
  2. Managing the domain with an external DNS provider
    If it is using an external DNS provider there are some steps to go through to verify ownership of the domain. Also be aware that many DNS providers don’t support configuring the root domain (mycooldomain.com vs. www.mycoolrootdomain.com) to point to another domain (CNAME record), which is what we want when using custom domain with CloudFront. There is a trick to work around this issue if you absolutely must.
  3. Importing an existing SSL certificate
    You can also import an existing certificate if you have already purchased one or prefer to use another provider.

Options 1 and 3 are strait forward, either request or import a certificate for use. However, when using an external DNS provider and requesting a certificate from CertificateManager there are one important consideration. Does the provider support a CNAME or equivalent record at the domain root? This is required to send traffic from the root domain (eg. mycooldonaim.com) to the blog and not just a traffic from a sub domain (eg. www.mycooldomain.com or blog.mycooldomain.com). Many DNS provider support this, but many of the registrars do not.
Some providers that support domain aliasing:

  • CloudFlare
  • DNSSimple
  • DNS Made Easy
  • easyDNS

If you must use a provider that doesn’t support domain aliasing, the work around is to configure the root domain to redirect to a sub domain (mycooldomain.com -> www.mycooldomain.com) and assign the CNAME to that subdomain. If the provider does not also provide SSL, you will be left in a situation where https traffic to the root domain fails and you will need to be carful not to share the https URL to the root domain (https://mycooldomain.com)

Once the certificate is in CertificateManager, note the ARN so that it can be used when configuring the deployment. Click on the certificate in CertificateManager to see the details including the ARN.

Setting up the blog

With the tools installed we can now create the project. Both serverless and hexo require starting with a new directory, so we create both and then combine them.

1
2
3
4
5
6
7
8
9
10
11
# Create a serverless project
serverless create --template aws-nodejs --path serverless-blog-sls

# Create a hexo project
hexo init serverless-blog

# Copy the serverless config and function to the hexo project and clean up
cp serverless-blog-sls/serverless.yml serverless-blog-sls/handler.js serverless-blog
rm -rf serverless-blog-sls

cd serverless-blog

Configure Serverless for AWS

In order to deploy the blog for us, serverless needs to be able to access our AWS account. Their documentation is pretty good, so I’m not going to try to recreate it.
Serverless Getting Started: AWS - Credentials

For the most flexible way to handle your AWS credentials, I recommend using an AWS profile config file where you can store all your AWS credential profiles.
AWS profile config

Configuring Serverless to deploy the blog

First we need to install the fullstack-serverless plugin-in to help create the stack we want on AWS

1
npm install --save-dev fullstack-serverless

and to setup serverless to use it add the following to your serverless.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
custom:
fullstack:
# Configure the domain after we set it up in AWS
# domain: my-custom-domain.com
# certificate: arn:aws:acm:us-east-1:... # The ARN for the SSL cert to use form AWS CertificateManager
bucketName: webapp-deploy # Unique name for the S3 bucket to host the client assets
distributionFolder: public # Path to the client assets to be uploaded to S3
indexDocument: index.html # The index document to use
errorDocument: error.html # The error document to use
singlePageApp: false
apiPath: api # The path prefix for your API Gateway lambdas.
clientCommand: hexo clean && hexo generate # Command to generate the client assets. Defaults to doing nothing
clientSrcPath: ./ # The path to where you want to run the clientCommand

plugins:
- fullstack-serverless

As well as set the AWS profile to use if you decided to configure your credentials that way. Replace the madskills profile with your profile name.

1
2
3
4
provider:
name: aws
runtime: nodejs6.10
profile: madskills

Now we can deploy the first version of the blog, run

1
serverless deploy

to deploy the serverless stack. This will take several minutes (20 minutes, sometimes more) the first time while the CloudFront distribution is created. While that is running we will start creating the accounts we will need.

Write then!

We now have a

Connecting with an audience

With a blog deployed and running, we can now start publishing content and driving traffic to it. But what happens to the visitors once they leave? How do you bring them back? Installing analytics, tracking pixels for remarketing, and setting up a mailing list are great ways to be able to engage the people that read the awesome content we are going to write. Regardless of what the goal of this blog is, knowing what the traffic it receives looks like is useful. Adding an analytics tool (Google Analytics) will tell us about the traffic the blog gets as well as information about what kind of people visit it. Knowing what traffic the site gets, and a little about who visits it is very helpful for many things, but what if you want to reach out to the visitors later? Remarketing pixels will allow us to show ads to people who have visited us at some point in the future, or if they sign up for our mailing list we can reach out directly. Setting these things up is not hard, but it can take some time, and does require including a Privacy Policy and possibly Terms of Service if you are offering a product. Once these tools are in place we will be able to take full advantage on the traffic to the blog in the future with little extra work.

Google Tag Manager

Setting up tracking pixels takes more work than you might expect, and adding code for each one can get messy. Google Tag Manager allows you to install one code snippet, and then manage installing all your other tags from a web portal. It removed the need to deploy code changes when you install each tag.
The first thing that needs to be done is create Google Tag Manager and Analytics accounts for the site.
https://marketingplatform.google.com/about/

With a web property setup in Google Analytics and an account for the blog in Google Tag Manager, the next step is to install the Google Tag Manager code on the site. Follow the instructions Google provides to get the most up to date code and add it to the hexo theme. Commonly Google Analytics is installed in themes/<theme>/layout/_partial/head.ejs by including google-analytics.ejs (locations may vary with different themes)

1
<%- partial('google-analytics') %>

A simple way to use GTM instead is to modify google-analytics.ejs to load GTM instead of Analytics (GTM will install your Analytics tag for you).

1
2
3
4
5
6
7
8
9
<% if (theme.google_tag_manager){ %>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<%= theme.google_tag_manager %>');</script>
<!-- End Google Tag Manager -->
<% } %>

A <noscript> block also needs to be included in the <body> of each page. Include this in themes/<theme>/layout/index.ejs and any other place it is needed for posts.

1
2
3
4
5
6
<% if (theme.google_tag_manager){ %>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<%= theme.google_tag_manager %>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<% } %>

then add the GTM ID to themes/<theme>/_config.yaml

1
google_tag_manager: GTM-yourGTMId

Deploy the changes so that Google Tag Manager can verify the instalation.

1
serverless client deploy

Installing Google Analytics

With Google Tag Manager installed we can now start adding tags. The quickest to add is Google Analytics.

  • Click ‘New Tag’
  • Select ‘Google Analytics - Universal Analytics’
  • Configure you Google Analytics ID
  • Add an ‘All Pages’ trigger

Once it is created submit the changes and it will be live on the site!

Creating social pixel accounts

Adding a mailing list

Disqus?

Setting up a privacy page

TOS, etc if you offer software to install

See
https://support.google.com/adwordspolicy/answer/6020954#311