You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Angular SEO Part 1 - Full Search Engine Optimization Solution for PWAs
Episode 66 written by Jeff DelaneyThe single most common question I receive is How do I make Angular SEO friendly. Usually my answer is Well, it’s complicated… no more. Today I bring you a simple solution to this very important problem.
I am going to show you a novel SEO strategy to make an Angular5 (or any Progressive Web App for that matter) visible to search engine crawlers and social media link preview bots. If you’ve tried to make Angular2+ SEO friendly in the past, you might have experience working through server-side rendering (SSR) or Angular Universal tutorials that are either difficult to implement or simply do not work. I have never seen a working server side rendering solution with Angular and AngularFire2 (Firebase) - until now.
All of this magic is made possible via Headless Chrome and Rendertron - a web browser that runs on the server.
Full source code for Angular SEO with Rendertron and the Live Demo.
What are the benefits of this approach?
- Fully compatible all search crawlers.
- Fully compatible with Linkbots (Facebook/Twitter previews).
- Fully compatible with Firebase, AngularFire2, or any other data source.
- Easy to implement and test in an existing app.
- Does NOT require Angular Universal or any weird hacks.
What are the drawbacks?
- Requires a Rentertron instance to be deployed for production (Docker container).
- Performance hit on first page view (except the root URL).
- Potentially higher costs
- That’s all I could come up with…
I am happy to present you with the first-ever end-to-end Angular SEO tutorial that works for virtually any existing web app.
Initial Setup
I am starting from a brand new Angular v5 app with the routing module. Using the Angular router is essential for SEO because bots need URLS and links to follow in your app.
ng new seoFriendlyApp --routing |
The next step is to create a few components and load them with the router. Each component will have it’s own dynamically generated meta tags to be used by social media bots and search crawlers.
ng g component home-page |
app.router.module
Your router should look something like this - typical Angular stuff:
import { NgModule } from '@angular/core'; |
Optional - AngularFire2
I am also using AngularFire2 to show you that search friendly content is possible with Angular and asynchronous Firebase data. If you want to build the firebase component in this tutorial, follow the install instructions on the official repo first.
What is Rendertron and Headless Chrome?
I highly Recommend that you watch Sam Li’s Rendertron talk at Polymer Summit 2017.
Headless chrome is just a regular Chrome browser that runs on the server - it renders and serializes web pages but never displays them on a screen.
Rendertron is an app created by the Chrome team that uses headless browsing to render and serialize content from a URL. The app makes it easy to just point your server to a url, then get the rendered HTML page back as a string, along with all your linkbot meta tags and async firebase data included. When a bot navigates to your URL, it will:
- Wait for page load and async operations.
- Wait for network requests to complete (i.e. Firebase database).
- You can even send custom events to signal a complete load.
- Respond with the fully rendered page.
Deploy a Rendertron Container for Production
If you’re just experimenting, you can skip this step and use the official Rendertron demo. It has no uptime guarantee and will not scale, but you’re allowed to use it for fun. I will be using it throughout the tutorial.
If you’re using Rendertron SSR for production, you will need to deploy your own instance of the app to have control over scaling and ensure guaranteed uptime. It’s a Dockerized package, which makes it very easy to deploy to Google App Engine or AWS.
On my local system, I had issues installing the NPM package directly. I was able to get a working version with Docker with the following steps (Keep in mind, Rendertron is a cutting edge package, so things may have changed by the time you read this).
First, install Docker. The steps vary based on your OS.
Next, run these commands from the root of your Angular project or in a separate directory if you want to treat it as a standalone project. It will take a few minutes to build the container.
git clone https://github.com/GoogleChrome/rendertron.git server |
If you run into errors at this point, head to the official docs trouble shooting commands.
If everything went according to plan, you should have a working rendertron app at https://http://localhost:8080
.
Deploying to GCP
If you have an existing Firebase project, you can easily deploy your own instance of Rendertron to GCP App Engine with a single command.
Rendertron needs to run in a custom App Engine flex environment, which is defined by its Dockerfile. You can adjust the app.yaml
settings to limit the number of instances and memory to control costs. Keep in mind, you are not required to deploy to App Engine - you have a Docker container that can be deployed anywhere.
gcloud app deploy app.yaml --project YOUR-PROJECT |
Setting Social Media Meta Tags in Angular
Now that we have the Rendertron server ready to go, let’s use Angular’s Meta service to dynamically generate meta tags for Facebook Open Graph and Twitter Cards. I am going to show you how to accomplish this with both static values and with backend data pulled from Firebase.
Our goal is to create a valid Twitter card (or any social media platform) that looks like this.
index.html
In addition the service, it’s a good idea to hard-code meta tags as default fallback. Their content should usually reflect the content of your home page.
Add the following tags inside the <head>
of the index.html
file and customize the content for your brand.
<!-- twitter --> |
seo.service.ts
We are going to be updating these default meta tags dynamically for each component that is loaded with the router. The SeoService
is a DRY and convenient place to organize this code in Angular.
ng g service seo --module app |
The generateTags
methods takes a configuration object as an argument, then updates all of the meta tags dynamically. If you forget to pass it a config object, it will fallback to the defaults listed below. You will most likely want to customize this service with your own config options and tags - it’s not designed to be one-size-fits-all.
import { Injectable } from '@angular/core'; |
Setting Meta Tags in a Component
Now that we have a working service let’s put it to use in the components.
contact-page.component.ts
It’s as easy as calling the generateTags
method when the component is initialized. If you open dev tools, you should see the meta tags change when navigating between routes.
import { Component, OnInit } from '@angular/core'; |
You can leave the component HTML unchanged, it has no impact on the meta tag rendering for linkbots.
firebase-demo.component.ts
To round out a complete solution, let’s show Firebase data to search engine crawlers and linkbots.
If you were planning on using Angular Universal server-side-rendering with AngularFire2 - good luck to you. These two libraries are not compatible and I have no idea if there is a good plan to make the two play well together. That’s why I am so excited about Headless Chrome.
Amazingly, you don’t have to do anything special here. Just subscribe to the Firebase data during NgOnInit
and use its emitted values to update the metatags. Rendertron will wait for this activity to complete, then display the dynamic data to bots.
import { Component, OnInit } from '@angular/core'; |
Up Next
At this point, your app should be displaying meta tags, but we still need a way to handle incoming traffic and choose the appropriate rendering technique.
The next step is to configure the middleware that can filter traffic based on whether it’s a bot or a real human. You can configure this on any server, but we are going to use Firebase Cloud Functions so it can be easily integrated with Firebase hosting.
Let’s keep it moving -> Angular SEO Part 2